//package com.xdtech.core.annotation;
//
///*
// * Hibernate, Relational Persistence for Idiomatic Java
// *
// * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
// * indicated by the @author tags or express copyright attribution
// * statements applied by the authors.  All third-party contributions are
// * distributed under license by Red Hat Inc.
// *
// * This copyrighted material is made available to anyone wishing to use, modify,
// * copy, or redistribute it subject to the terms and conditions of the GNU
// * Lesser General Public License, as published by the Free Software Foundation.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// * for more details.
// *
// * You should have received a copy of the GNU Lesser General Public License
// * along with this distribution; if not, write to:
// * Free Software Foundation, Inc.
// * 51 Franklin Street, Fifth Floor
// * Boston, MA  02110-1301  USA
// */
//
//import java.io.File;
//import java.io.FileInputStream;
//import java.io.FileNotFoundException;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.io.InputStream;
//import java.io.ObjectInputStream;
//import java.io.Serializable;
//import java.io.StringReader;
//import java.lang.reflect.Array;
//import java.lang.reflect.Constructor;
//import java.lang.reflect.InvocationTargetException;
//import java.lang.reflect.Method;
//import java.net.URL;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Collections;
//import java.util.Enumeration;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.Iterator;
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.ListIterator;
//import java.util.Map;
//import java.util.Properties;
//import java.util.ResourceBundle;
//import java.util.Set;
//import java.util.StringTokenizer;
//import java.util.TreeMap;
//import java.util.jar.JarFile;
//import java.util.zip.ZipEntry;
//
//import javax.persistence.Embeddable;
//import javax.persistence.Entity;
//import javax.persistence.MapsId;
//
//import org.dom4j.Attribute;
//import org.dom4j.Document;
//import org.dom4j.DocumentException;
//import org.dom4j.Element;
//import org.hibernate.AnnotationException;
//import org.hibernate.DuplicateMappingException;
//import org.hibernate.EmptyInterceptor;
//import org.hibernate.HibernateException;
//import org.hibernate.Interceptor;
//import org.hibernate.InvalidMappingException;
//import org.hibernate.MappingException;
//import org.hibernate.MappingNotFoundException;
//import org.hibernate.SessionFactory;
//import org.hibernate.SessionFactoryObserver;
//import org.hibernate.annotations.AnyMetaDef;
//import org.hibernate.annotations.common.reflection.MetadataProvider;
//import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
//import org.hibernate.annotations.common.reflection.ReflectionManager;
//import org.hibernate.annotations.common.reflection.XClass;
//import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
//import org.hibernate.cfg.AnnotatedClassType;
//import org.hibernate.cfg.AnnotationBinder;
//import org.hibernate.cfg.MyConfiguration;
//import org.hibernate.cfg.CopyIdentifierComponentSecondPass;
//import org.hibernate.cfg.CreateKeySecondPass;
//import org.hibernate.cfg.EJB3DTDEntityResolver;
//import org.hibernate.cfg.EJB3NamingStrategy;
//import org.hibernate.cfg.Environment;
//import org.hibernate.cfg.ExtendedMappings;
//import org.hibernate.cfg.ExtendsQueueEntry;
//import org.hibernate.cfg.FkSecondPass;
//import org.hibernate.cfg.HbmBinder;
//import org.hibernate.cfg.InheritanceState;
//import org.hibernate.cfg.Mappings;
//import org.hibernate.cfg.Mappings.PropertyReference;
//import org.hibernate.cfg.MetadataSourceType;
//import org.hibernate.cfg.NamingStrategy;
//import org.hibernate.cfg.ObjectNameNormalizer;
//import org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass;
//import org.hibernate.cfg.PropertyData;
//import org.hibernate.cfg.QuerySecondPass;
//import org.hibernate.cfg.RecoverableException;
//import org.hibernate.cfg.SecondPass;
//import org.hibernate.cfg.SecondaryTableSecondPass;
//import org.hibernate.cfg.SetSimpleValueTypeSecondPass;
//import org.hibernate.cfg.Settings;
//import org.hibernate.cfg.SettingsFactory;
//import org.hibernate.cfg.UniqueConstraintHolder;
//import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
//import org.hibernate.cfg.beanvalidation.BeanValidationActivator;
//import org.hibernate.dialect.Dialect;
//import org.hibernate.dialect.MySQLDialect;
//import org.hibernate.dialect.function.SQLFunction;
//import org.hibernate.engine.FilterDefinition;
//import org.hibernate.engine.Mapping;
//import org.hibernate.engine.NamedQueryDefinition;
//import org.hibernate.engine.NamedSQLQueryDefinition;
//import org.hibernate.engine.ResultSetMappingDefinition;
//import org.hibernate.event.AutoFlushEventListener;
//import org.hibernate.event.DeleteEventListener;
//import org.hibernate.event.DirtyCheckEventListener;
//import org.hibernate.event.EventListeners;
//import org.hibernate.event.EvictEventListener;
//import org.hibernate.event.FlushEntityEventListener;
//import org.hibernate.event.FlushEventListener;
//import org.hibernate.event.InitializeCollectionEventListener;
//import org.hibernate.event.LoadEventListener;
//import org.hibernate.event.LockEventListener;
//import org.hibernate.event.MergeEventListener;
//import org.hibernate.event.PersistEventListener;
//import org.hibernate.event.PostCollectionRecreateEventListener;
//import org.hibernate.event.PostCollectionRemoveEventListener;
//import org.hibernate.event.PostCollectionUpdateEventListener;
//import org.hibernate.event.PostDeleteEventListener;
//import org.hibernate.event.PostInsertEventListener;
//import org.hibernate.event.PostLoadEventListener;
//import org.hibernate.event.PostUpdateEventListener;
//import org.hibernate.event.PreCollectionRecreateEventListener;
//import org.hibernate.event.PreCollectionRemoveEventListener;
//import org.hibernate.event.PreCollectionUpdateEventListener;
//import org.hibernate.event.PreDeleteEventListener;
//import org.hibernate.event.PreInsertEventListener;
//import org.hibernate.event.PreLoadEventListener;
//import org.hibernate.event.PreUpdateEventListener;
//import org.hibernate.event.RefreshEventListener;
//import org.hibernate.event.ReplicateEventListener;
//import org.hibernate.event.SaveOrUpdateEventListener;
//import org.hibernate.id.IdentifierGenerator;
//import org.hibernate.id.IdentifierGeneratorAggregator;
//import org.hibernate.id.PersistentIdentifierGenerator;
//import org.hibernate.id.factory.DefaultIdentifierGeneratorFactory;
//import org.hibernate.id.factory.IdentifierGeneratorFactory;
//import org.hibernate.impl.SessionFactoryImpl;
//import org.hibernate.mapping.AuxiliaryDatabaseObject;
//import org.hibernate.mapping.Collection;
//import org.hibernate.mapping.Column;
//import org.hibernate.mapping.DenormalizedTable;
//import org.hibernate.mapping.FetchProfile;
//import org.hibernate.mapping.ForeignKey;
//import org.hibernate.mapping.IdGenerator;
//import org.hibernate.mapping.IdentifierCollection;
//import org.hibernate.mapping.Index;
//import org.hibernate.mapping.Join;
//import org.hibernate.mapping.MappedSuperclass;
//import org.hibernate.mapping.MetadataSource;
//import org.hibernate.mapping.PersistentClass;
//import org.hibernate.mapping.Property;
//import org.hibernate.mapping.RootClass;
//import org.hibernate.mapping.SimpleValue;
//import org.hibernate.mapping.Table;
//import org.hibernate.mapping.TypeDef;
//import org.hibernate.mapping.UniqueKey;
//import org.hibernate.persister.PersisterClassProvider;
//import org.hibernate.proxy.EntityNotFoundDelegate;
//import org.hibernate.secure.JACCMyConfiguration;
//import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
//import org.hibernate.tool.hbm2ddl.IndexMetadata;
//import org.hibernate.tool.hbm2ddl.TableMetadata;
//import org.hibernate.tuple.entity.EntityTuplizerFactory;
//import org.hibernate.type.BasicType;
//import org.hibernate.type.SerializationException;
//import org.hibernate.type.Type;
//import org.hibernate.type.TypeResolver;
//import org.hibernate.usertype.CompositeUserType;
//import org.hibernate.usertype.UserType;
//import org.hibernate.util.ArrayHelper;
//import org.hibernate.util.CollectionHelper;
//import org.hibernate.util.ConfigHelper;
//import org.hibernate.util.JoinedIterator;
//import org.hibernate.util.PropertiesHelper;
//import org.hibernate.util.ReflectHelper;
//import org.hibernate.util.SerializationHelper;
//import org.hibernate.util.StringHelper;
//import org.hibernate.util.XMLHelper;
//import org.hibernate.util.xml.MappingReader;
//import org.hibernate.util.xml.Origin;
//import org.hibernate.util.xml.OriginImpl;
//import org.hibernate.util.xml.XmlDocument;
//import org.hibernate.util.xml.XmlDocumentImpl;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.xml.sax.EntityResolver;
//import org.xml.sax.InputSource;
//
//public class MyConfiguration implements Serializable {
//	/**
//	 * 
//	 */
//	private static final long serialVersionUID = 1L;
//
//	private static Logger log = LoggerFactory
//			.getLogger(MyMyConfiguration.class);
//
//	/**
//	 * Setting used to give the name of the default
//	 * {@link org.hibernate.annotations.CacheConcurrencyStrategy} to use when
//	 * either {@link javax.persistence.Cacheable @Cacheable} or
//	 * {@link org.hibernate.annotations.Cache @Cache} is used.
//	 * {@link org.hibernate.annotations.Cache @Cache(strategy="..")} is used to
//	 * override.
//	 */
//	public static final String DEFAULT_CACHE_CONCURRENCY_STRATEGY = "hibernate.cache.default_cache_concurrency_strategy";
//
//	/**
//	 * Setting which indicates whether or not the new
//	 * {@link org.hibernate.id.IdentifierGenerator} are used for AUTO, TABLE and
//	 * SEQUENCE. Default to false to keep backward compatibility.
//	 */
//	public static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id.new_generator_mappings";
//
//	public static final String ARTEFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
//
//	/**
//	 * Class name of the class needed to enable Search.
//	 */
//	private static final String SEARCH_STARTUP_CLASS = "org.hibernate.search.event.EventListenerRegister";
//
//	/**
//	 * Method to call to enable Search.
//	 */
//	private static final String SEARCH_STARTUP_METHOD = "enableHibernateSearch";
//
//	protected MetadataSourceQueue metadataSourceQueue;
//	private transient ReflectionManager reflectionManager;
//
//	protected Map<String, PersistentClass> classes;
//	protected Map<String, String> imports;
//	protected Map<String, Collection> collections;
//	protected Map<String, Table> tables;
//	protected List<AuxiliaryDatabaseObject> auxiliaryDatabaseObjects;
//
//	protected Map<String, NamedQueryDefinition> namedQueries;
//	protected Map<String, NamedSQLQueryDefinition> namedSqlQueries;
//	protected Map<String, ResultSetMappingDefinition> sqlResultSetMappings;
//
//	protected Map<String, TypeDef> typeDefs;
//	protected Map<String, FilterDefinition> filterDefinitions;
//	protected Map<String, FetchProfile> fetchProfiles;
//
//	protected Map tableNameBinding;
//	protected Map columnNameBindingPerTable;
//
//	protected List<SecondPass> secondPasses;
//	protected List<Mappings.PropertyReference> propertyReferences;
//	protected Map<ExtendsQueueEntry, ?> extendsQueue;
//
//	protected Map<String, SQLFunction> sqlFunctions;
//	private TypeResolver typeResolver = new TypeResolver();
//
//	private EntityTuplizerFactory entityTuplizerFactory;
//	// private ComponentTuplizerFactory componentTuplizerFactory; todo :
//	// HHH-3517 and HHH-1907
//
//	private Interceptor interceptor;
//	private Properties properties;
//	private EntityResolver entityResolver;
//	private EntityNotFoundDelegate entityNotFoundDelegate;
//
//	protected transient XMLHelper xmlHelper;
//	protected NamingStrategy namingStrategy;
//	private PersisterClassProvider persisterClassProvider;
//	private SessionFactoryObserver sessionFactoryObserver;
//
//	private EventListeners eventListeners;
//
//	protected final SettingsFactory settingsFactory;
//
//	private transient Mapping mapping = buildMapping();
//
//	private DefaultIdentifierGeneratorFactory identifierGeneratorFactory;
//
//	private Map<Class<?>, org.hibernate.mapping.MappedSuperclass> mappedSuperClasses;
//
//	private Map<String, IdGenerator> namedGenerators;
//	private Map<String, Map<String, Join>> joins;
//	private Map<String, AnnotatedClassType> classTypes;
//	private Set<String> defaultNamedQueryNames;
//	private Set<String> defaultNamedNativeQueryNames;
//	private Set<String> defaultSqlResultSetMappingNames;
//	private Set<String> defaultNamedGenerators;
//	private Map<String, Properties> generatorTables;
//	private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
//	private Map<String, String> mappedByResolver;
//	private Map<String, String> propertyRefResolver;
//	private Map<String, AnyMetaDef> anyMetaDefs;
//	private List<CacheHolder> caches;
//	private boolean inSecondPass = false;
//	private boolean isDefaultProcessed = false;
//	private boolean isValidatorNotPresentLogged;
//	private Map<XClass, Map<String, PropertyData>> propertiesAnnotatedWithMapsId;
//	private Map<XClass, Map<String, PropertyData>> propertiesAnnotatedWithIdAndToOne;
//	private boolean specjProprietarySyntaxEnabled;
//
//	protected MyConfiguration(SettingsFactory settingsFactory) {
//		this.settingsFactory = settingsFactory;
//		reset();
//	}
//
//	public MyConfiguration() {
//		this(new SettingsFactory());
//	}
//
//	protected void reset() {
//		metadataSourceQueue = new MetadataSourceQueue();
//		createReflectionManager();
//
//		classes = new HashMap<String, PersistentClass>();
//		imports = new HashMap<String, String>();
//		collections = new HashMap<String, Collection>();
//		tables = new TreeMap<String, Table>();
//
//		namedQueries = new HashMap<String, NamedQueryDefinition>();
//		namedSqlQueries = new HashMap<String, NamedSQLQueryDefinition>();
//		sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
//
//		typeDefs = new HashMap<String, TypeDef>();
//		filterDefinitions = new HashMap<String, FilterDefinition>();
//		fetchProfiles = new HashMap<String, FetchProfile>();
//		auxiliaryDatabaseObjects = new ArrayList<AuxiliaryDatabaseObject>();
//
//		tableNameBinding = new HashMap();
//		columnNameBindingPerTable = new HashMap();
//
//		secondPasses = new ArrayList<SecondPass>();
//		propertyReferences = new ArrayList<Mappings.PropertyReference>();
//		extendsQueue = new HashMap<ExtendsQueueEntry, String>();
//
//		xmlHelper = new XMLHelper();
//		interceptor = EmptyInterceptor.INSTANCE;
//		properties = Environment.getProperties();
//		entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
//		eventListeners = new EventListeners();
//
//		sqlFunctions = new HashMap<String, SQLFunction>();
//
//		entityTuplizerFactory = new EntityTuplizerFactory();
//		// componentTuplizerFactory = new ComponentTuplizerFactory();
//
//		identifierGeneratorFactory = new DefaultIdentifierGeneratorFactory();
//
//		mappedSuperClasses = new HashMap<Class<?>, MappedSuperclass>();
//
//		metadataSourcePrecedence = Collections.emptyList();
//
//		namedGenerators = new HashMap<String, IdGenerator>();
//		joins = new HashMap<String, Map<String, Join>>();
//		classTypes = new HashMap<String, AnnotatedClassType>();
//		generatorTables = new HashMap<String, Properties>();
//		defaultNamedQueryNames = new HashSet<String>();
//		defaultNamedNativeQueryNames = new HashSet<String>();
//		defaultSqlResultSetMappingNames = new HashSet<String>();
//		defaultNamedGenerators = new HashSet<String>();
//		uniqueConstraintHoldersByTable = new HashMap<Table, List<UniqueConstraintHolder>>();
//		mappedByResolver = new HashMap<String, String>();
//		propertyRefResolver = new HashMap<String, String>();
//		caches = new ArrayList<CacheHolder>();
//		namingStrategy = EJB3NamingStrategy.INSTANCE;
//		persisterClassProvider = null;
//		setEntityResolver(new EJB3DTDEntityResolver());
//		anyMetaDefs = new HashMap<String, AnyMetaDef>();
//		propertiesAnnotatedWithMapsId = new HashMap<XClass, Map<String, PropertyData>>();
//		propertiesAnnotatedWithIdAndToOne = new HashMap<XClass, Map<String, PropertyData>>();
//		specjProprietarySyntaxEnabled = System
//				.getProperty("hibernate.enable_specj_proprietary_syntax") != null;
//	}
//
//	public EntityTuplizerFactory getEntityTuplizerFactory() {
//		return entityTuplizerFactory;
//	}
//
//	public ReflectionManager getReflectionManager() {
//		return reflectionManager;
//	}
//
//	// public ComponentTuplizerFactory getComponentTuplizerFactory() {
//	// return componentTuplizerFactory;
//	// }
//
//	/**
//	 * Iterate the entity mappings
//	 * 
//	 * @return Iterator of the entity mappings currently contained in the
//	 *         MyConfiguration.
//	 */
//	public Iterator<PersistentClass> getClassMappings() {
//		return classes.values().iterator();
//	}
//
//	/**
//	 * Iterate the collection mappings
//	 * 
//	 * @return Iterator of the collection mappings currently contained in the
//	 *         MyConfiguration.
//	 */
//	public Iterator getCollectionMappings() {
//		return collections.values().iterator();
//	}
//
//	/**
//	 * Iterate the table mappings
//	 * 
//	 * @return Iterator of the table mappings currently contained in the
//	 *         MyConfiguration.
//	 */
//	public Iterator<Table> getTableMappings() {
//		return tables.values().iterator();
//	}
//
//	/**
//	 * Iterate the mapped super class mappings EXPERIMENTAL Consider this API as
//	 * PRIVATE
//	 * 
//	 * @return iterator over the MappedSuperclass mapping currently contained in
//	 *         the MyConfiguration.
//	 */
//	public Iterator<MappedSuperclass> getMappedSuperclassMappings() {
//		return mappedSuperClasses.values().iterator();
//	}
//
//	/**
//	 * Get the mapping for a particular entity
//	 * 
//	 * @param entityName
//	 *            An entity name.
//	 * @return the entity mapping information
//	 */
//	public PersistentClass getClassMapping(String entityName) {
//		return classes.get(entityName);
//	}
//
//	/**
//	 * Get the mapping for a particular collection role
//	 * 
//	 * @param role
//	 *            a collection role
//	 * @return The collection mapping information
//	 */
//	public Collection getCollectionMapping(String role) {
//		return collections.get(role);
//	}
//
//	/**
//	 * Set a custom entity resolver. This entity resolver must be set before
//	 * addXXX(misc) call. Default value is
//	 * {@link org.hibernate.util.DTDEntityResolver}
//	 * 
//	 * @param entityResolver
//	 *            entity resolver to use
//	 */
//	public void setEntityResolver(EntityResolver entityResolver) {
//		this.entityResolver = entityResolver;
//	}
//
//	public EntityResolver getEntityResolver() {
//		return entityResolver;
//	}
//
//	/**
//	 * Retrieve the user-supplied delegate to handle non-existent entity
//	 * scenarios. May be null.
//	 * 
//	 * @return The user-supplied delegate
//	 */
//	public EntityNotFoundDelegate getEntityNotFoundDelegate() {
//		return entityNotFoundDelegate;
//	}
//
//	/**
//	 * Specify a user-supplied delegate to be used to handle scenarios where an
//	 * entity could not be located by specified id. This is mainly intended for
//	 * EJB3 implementations to be able to control how proxy initialization
//	 * errors should be handled...
//	 * 
//	 * @param entityNotFoundDelegate
//	 *            The delegate to use
//	 */
//	public void setEntityNotFoundDelegate(
//			EntityNotFoundDelegate entityNotFoundDelegate) {
//		this.entityNotFoundDelegate = entityNotFoundDelegate;
//	}
//
//	/**
//	 * Read mappings from a particular XML file
//	 * 
//	 * @param xmlFile
//	 *            a path to a file
//	 * @return this (for method chaining purposes)
//	 * @throws org.hibernate.MappingException
//	 *             Indicates inability to locate or parse the specified mapping
//	 *             file.
//	 * @see #addFile(java.io.File)
//	 */
//	public MyConfiguration addFile(String xmlFile) throws MappingException {
//		return addFile(new File(xmlFile));
//	}
//
//	/**
//	 * Read mappings from a particular XML file
//	 * 
//	 * @param xmlFile
//	 *            a path to a file
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates inability to locate the specified mapping file.
//	 *             Historically this could have indicated a problem parsing the
//	 *             XML document, but that is now delayed until after
//	 *             {@link #buildMappings}
//	 */
//	public MyConfiguration addFile(final File xmlFile) throws MappingException {
//		log.info("Reading mappings from file: " + xmlFile.getPath());
//		final String name = xmlFile.getAbsolutePath();
//		final InputSource inputSource;
//		try {
//			inputSource = new InputSource(new FileInputStream(xmlFile));
//		} catch (FileNotFoundException e) {
//			throw new MappingNotFoundException("file", xmlFile.toString());
//		}
//		add(inputSource, "file", name);
//		return this;
//	}
//
//	private XmlDocument add(InputSource inputSource, String originType,
//			String originName) {
//		return add(inputSource, new OriginImpl(originType, originName));
//	}
//
//	private XmlDocument add(InputSource inputSource, Origin origin) {
//		XmlDocument metadataXml = MappingReader.INSTANCE.readMappingDocument(
//				entityResolver, inputSource, origin);
//		add(metadataXml);
//		return metadataXml;
//	}
//
//	public void add(XmlDocument metadataXml) {
//		if (inSecondPass || !isOrmXml(metadataXml)) {
//			metadataSourceQueue.add(metadataXml);
//		} else {
//			final MetadataProvider metadataProvider = ((MetadataProviderInjector) reflectionManager)
//					.getMetadataProvider();
//			JPAMetadataProvider jpaMetadataProvider = (JPAMetadataProvider) metadataProvider;
//			List<String> classNames = jpaMetadataProvider.getXMLContext()
//					.addDocument(metadataXml.getDocumentTree());
//			for (String className : classNames) {
//				try {
//					metadataSourceQueue.add(reflectionManager.classForName(
//							className, this.getClass()));
//				} catch (ClassNotFoundException e) {
//					throw new AnnotationException(
//							"Unable to load class defined in XML: " + className,
//							e);
//				}
//			}
//		}
//	}
//
//	private static boolean isOrmXml(XmlDocument xmlDocument) {
//		return "entity-mappings".equals(xmlDocument.getDocumentTree()
//				.getRootElement().getName());
//	}
//
//	/**
//	 * Add a cached mapping file. A cached file is a serialized representation
//	 * of the DOM structure of a particular mapping. It is saved from a previous
//	 * call as a file with the name <tt>xmlFile + ".bin"</tt> where xmlFile is
//	 * the name of the original mapping file. </p> If a cached
//	 * <tt>xmlFile + ".bin"</tt> exists and is newer than <tt>xmlFile</tt> the
//	 * <tt>".bin"</tt> file will be read directly. Otherwise xmlFile is read and
//	 * then serialized to <tt>xmlFile + ".bin"</tt> for use the next time.
//	 * 
//	 * @param xmlFile
//	 *            The cacheable mapping file to be added.
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the cached file or processing the
//	 *             non-cached file.
//	 */
//	public MyConfiguration addCacheableFile(File xmlFile)
//			throws MappingException {
//		File cachedFile = determineCachedDomFile(xmlFile);
//
//		try {
//			return addCacheableFileStrictly(xmlFile);
//		} catch (SerializationException e) {
//			log.warn("Could not deserialize cache file: "
//					+ cachedFile.getPath() + " : " + e);
//		} catch (FileNotFoundException e) {
//			log.warn("I/O reported cached file could not be found : "
//					+ cachedFile.getPath() + " : " + e);
//		}
//
//		final String name = xmlFile.getAbsolutePath();
//		final InputSource inputSource;
//		try {
//			inputSource = new InputSource(new FileInputStream(xmlFile));
//		} catch (FileNotFoundException e) {
//			throw new MappingNotFoundException("file", xmlFile.toString());
//		}
//
//		log.info("Reading mappings from file: " + xmlFile);
//		XmlDocument metadataXml = add(inputSource, "file", name);
//
//		try {
//			log.debug("Writing cache file for: " + xmlFile + " to: "
//					+ cachedFile);
//			SerializationHelper.serialize(
//					(Serializable) metadataXml.getDocumentTree(),
//					new FileOutputStream(cachedFile));
//		} catch (SerializationException e) {
//			log.warn("Could not write cached file: " + cachedFile, e);
//		} catch (FileNotFoundException e) {
//			log.warn(
//					"I/O reported error writing cached file : "
//							+ cachedFile.getPath(), e);
//		}
//
//		return this;
//	}
//
//	private File determineCachedDomFile(File xmlFile) {
//		return new File(xmlFile.getAbsolutePath() + ".bin");
//	}
//
//	/**
//	 * <b>INTENDED FOR TESTSUITE USE ONLY!</b>
//	 * <p/>
//	 * Much like {@link #addCacheableFile(File)} except that here we will fail
//	 * immediately if the cache version cannot be found or used for whatever
//	 * reason
//	 * 
//	 * @param xmlFile
//	 *            The xml file, not the bin!
//	 * 
//	 * @return The dom "deserialized" from the cached file.
//	 * 
//	 * @throws SerializationException
//	 *             Indicates a problem deserializing the cached dom tree
//	 * @throws FileNotFoundException
//	 *             Indicates that the cached file was not found or was not
//	 *             usable.
//	 */
//	public MyConfiguration addCacheableFileStrictly(File xmlFile)
//			throws SerializationException, FileNotFoundException {
//		final File cachedFile = determineCachedDomFile(xmlFile);
//
//		final boolean useCachedFile = xmlFile.exists() && cachedFile.exists()
//				&& xmlFile.lastModified() < cachedFile.lastModified();
//
//		if (!useCachedFile) {
//			throw new FileNotFoundException(
//					"Cached file could not be found or could not be used");
//		}
//
//		log.info("Reading mappings from cache file: " + cachedFile);
//		Document document = (Document) SerializationHelper
//				.deserialize(new FileInputStream(cachedFile));
//		add(new XmlDocumentImpl(document, "file", xmlFile.getAbsolutePath()));
//		return this;
//	}
//
//	/**
//	 * Add a cacheable mapping file.
//	 * 
//	 * @param xmlFile
//	 *            The name of the file to be added. This must be in a form
//	 *            useable to simply construct a {@link java.io.File} instance.
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the cached file or processing the
//	 *             non-cached file.
//	 * @see #addCacheableFile(java.io.File)
//	 */
//	public MyConfiguration addCacheableFile(String xmlFile)
//			throws MappingException {
//		return addCacheableFile(new File(xmlFile));
//	}
//
//	/**
//	 * Read mappings from a <tt>String</tt>
//	 * 
//	 * @param xml
//	 *            an XML string
//	 * @return this (for method chaining purposes)
//	 * @throws org.hibernate.MappingException
//	 *             Indicates problems parsing the given XML string
//	 */
//	public MyConfiguration addXML(String xml) throws MappingException {
//		if (log.isDebugEnabled()) {
//			log.debug("Mapping XML:\n" + xml);
//		}
//		final InputSource inputSource = new InputSource(new StringReader(xml));
//		add(inputSource, "string", "XML String");
//		return this;
//	}
//
//	/**
//	 * Read mappings from a <tt>URL</tt>
//	 * 
//	 * @param url
//	 *            The url for the mapping document to be read.
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the URL or processing the mapping
//	 *             document.
//	 */
//	public MyConfiguration addURL(URL url) throws MappingException {
//		final String urlExternalForm = url.toExternalForm();
//
//		if (log.isDebugEnabled()) {
//			log.debug("Reading mapping document from URL : {}", urlExternalForm);
//		}
//
//		try {
//			add(url.openStream(), "URL", urlExternalForm);
//		} catch (IOException e) {
//			throw new InvalidMappingException("Unable to open url stream ["
//					+ urlExternalForm + "]", "URL", urlExternalForm, e);
//		}
//		return this;
//	}
//
//	private XmlDocument add(InputStream inputStream, final String type,
//			final String name) {
//		final InputSource inputSource = new InputSource(inputStream);
//		try {
//			return add(inputSource, type, name);
//		} finally {
//			try {
//				inputStream.close();
//			} catch (IOException ignore) {
//				log.trace("Was unable to close input stream");
//			}
//		}
//	}
//
//	/**
//	 * Read mappings from a DOM <tt>Document</tt>
//	 * 
//	 * @param doc
//	 *            The DOM document
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the DOM or processing the mapping
//	 *             document.
//	 */
//	public MyConfiguration addDocument(org.w3c.dom.Document doc)
//			throws MappingException {
//		if (log.isDebugEnabled()) {
//			log.debug("Mapping document:\n" + doc);
//		}
//
//		final Document document = xmlHelper.createDOMReader().read(doc);
//		add(new XmlDocumentImpl(document, "unknown", null));
//
//		return this;
//	}
//
//	/**
//	 * Read mappings from an {@link java.io.InputStream}.
//	 * 
//	 * @param xmlInputStream
//	 *            The input stream containing a DOM.
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the stream, or processing the
//	 *             contained mapping document.
//	 */
//	public MyConfiguration addInputStream(InputStream xmlInputStream)
//			throws MappingException {
//		add(xmlInputStream, "input stream", null);
//		return this;
//	}
//
//	/**
//	 * Read mappings as a application resource (i.e. classpath lookup).
//	 * 
//	 * @param resourceName
//	 *            The resource name
//	 * @param classLoader
//	 *            The class loader to use.
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems locating the resource or processing the
//	 *             contained mapping document.
//	 */
//	public MyConfiguration addResource(String resourceName,
//			ClassLoader classLoader) throws MappingException {
//		log.info("Reading mappings from resource: " + resourceName);
//		InputStream resourceInputStream = classLoader
//				.getResourceAsStream(resourceName);
//		if (resourceInputStream == null) {
//			throw new MappingNotFoundException("resource", resourceName);
//		}
//		add(resourceInputStream, "resource", resourceName);
//		return this;
//	}
//
//	/**
//	 * Read mappings as a application resourceName (i.e. classpath lookup)
//	 * trying different class loaders.
//	 * 
//	 * @param resourceName
//	 *            The resource name
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems locating the resource or processing the
//	 *             contained mapping document.
//	 */
//	public MyConfiguration addResource(String resourceName)
//			throws MappingException {
//		log.info("Reading mappings from resource : " + resourceName);
//		ClassLoader contextClassLoader = Thread.currentThread()
//				.getContextClassLoader();
//		InputStream resourceInputStream = null;
//		if (contextClassLoader != null) {
//			resourceInputStream = contextClassLoader
//					.getResourceAsStream(resourceName);
//		}
//		if (resourceInputStream == null) {
//			resourceInputStream = Environment.class.getClassLoader()
//					.getResourceAsStream(resourceName);
//		}
//		if (resourceInputStream == null) {
//			throw new MappingNotFoundException("resource", resourceName);
//		}
//		add(resourceInputStream, "resource", resourceName);
//		return this;
//	}
//
//	/**
//	 * Read a mapping as an application resource using the convention that a
//	 * class named <tt>foo.bar.Foo</tt> is mapped by a file
//	 * <tt>foo/bar/Foo.hbm.xml</tt> which can be resolved as a classpath
//	 * resource.
//	 * 
//	 * @param persistentClass
//	 *            The mapped class
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems locating the resource or processing the
//	 *             contained mapping document.
//	 */
//	public MyConfiguration addClass(Class persistentClass)
//			throws MappingException {
//		String mappingResourceName = persistentClass.getName()
//				.replace('.', '/') + ".hbm.xml";
//		log.info("Reading mappings from resource: " + mappingResourceName);
//		return addResource(mappingResourceName,
//				persistentClass.getClassLoader());
//	}
//
//	/**
//	 * Read metadata from the annotations associated with this class.
//	 * 
//	 * @param annotatedClass
//	 *            The class containing annotations
//	 * 
//	 * @return this (for method chaining)
//	 */
//	@SuppressWarnings({ "unchecked" })
//	public MyConfiguration addAnnotatedClass(Class annotatedClass) {
//		XClass xClass = reflectionManager.toXClass(annotatedClass);
//		metadataSourceQueue.add(xClass);
//		return this;
//	}
//
//	/**
//	 * Read package-level metadata.
//	 * 
//	 * @param packageName
//	 *            java package name
//	 * 
//	 * @return this (for method chaining)
//	 * 
//	 * @throws MappingException
//	 *             in case there is an error in the mapping data
//	 */
//	public MyConfiguration addPackage(String packageName)
//			throws MappingException {
//		log.info("Mapping package {}", packageName);
//		try {
//			AnnotationBinder.bindPackage(packageName, createMappings());
//			return this;
//		} catch (MappingException me) {
//			log.error("Could not parse the package-level metadata ["
//					+ packageName + "]");
//			throw me;
//		}
//	}
//
//	/**
//	 * Read all mappings from a jar file
//	 * <p/>
//	 * Assumes that any file named <tt>*.hbm.xml</tt> is a mapping document.
//	 * 
//	 * @param jar
//	 *            a jar file
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the jar file or processing the
//	 *             contained mapping documents.
//	 */
//	public MyConfiguration addJar(File jar) throws MappingException {
//		log.info("Searching for mapping documents in jar: " + jar.getName());
//		JarFile jarFile = null;
//		try {
//			try {
//				jarFile = new JarFile(jar);
//			} catch (IOException ioe) {
//				throw new InvalidMappingException(
//						"Could not read mapping documents from jar: "
//								+ jar.getName(), "jar", jar.getName(), ioe);
//			}
//			Enumeration jarEntries = jarFile.entries();
//			while (jarEntries.hasMoreElements()) {
//				ZipEntry ze = (ZipEntry) jarEntries.nextElement();
//				if (ze.getName().endsWith(".hbm.xml")) {
//					log.info("Found mapping document in jar: " + ze.getName());
//					try {
//						addInputStream(jarFile.getInputStream(ze));
//					} catch (Exception e) {
//						throw new InvalidMappingException(
//								"Could not read mapping documents from jar: "
//										+ jar.getName(), "jar", jar.getName(),
//								e);
//					}
//				}
//			}
//		} finally {
//			try {
//				if (jarFile != null) {
//					jarFile.close();
//				}
//			} catch (IOException ioe) {
//				log.error("could not close jar", ioe);
//			}
//		}
//
//		return this;
//	}
//
//	/**
//	 * Read all mapping documents from a directory tree.
//	 * <p/>
//	 * Assumes that any file named <tt>*.hbm.xml</tt> is a mapping document.
//	 * 
//	 * @param dir
//	 *            The directory
//	 * @return this (for method chaining purposes)
//	 * @throws MappingException
//	 *             Indicates problems reading the jar file or processing the
//	 *             contained mapping documents.
//	 */
//	public MyConfiguration addDirectory(File dir) throws MappingException {
//		File[] files = dir.listFiles();
//		for (File file : files) {
//			if (file.isDirectory()) {
//				addDirectory(file);
//			} else if (file.getName().endsWith(".hbm.xml")) {
//				addFile(file);
//			}
//		}
//		return this;
//	}
//
//	/**
//	 * Create a new <tt>Mappings</tt> to add class and collection mappings to.
//	 * 
//	 * @return The created mappings
//	 */
//	public Mappings createMappings() {
//		return new MappingsImpl();
//	}
//
//	@SuppressWarnings({ "unchecked" })
//	private Iterator<IdentifierGenerator> iterateGenerators(Dialect dialect)
//			throws MappingException {
//
//		TreeMap generators = new TreeMap();
//		String defaultCatalog = properties
//				.getProperty(Environment.DEFAULT_CATALOG);
//		String defaultSchema = properties
//				.getProperty(Environment.DEFAULT_SCHEMA);
//
//		for (PersistentClass pc : classes.values()) {
//			if (!pc.isInherited()) {
//				IdentifierGenerator ig = pc.getIdentifier()
//						.createIdentifierGenerator(
//								getIdentifierGeneratorFactory(), dialect,
//								defaultCatalog, defaultSchema, (RootClass) pc);
//
//				if (ig instanceof PersistentIdentifierGenerator) {
//					generators
//							.put(((PersistentIdentifierGenerator) ig)
//									.generatorKey(), ig);
//				} else if (ig instanceof IdentifierGeneratorAggregator) {
//					((IdentifierGeneratorAggregator) ig)
//							.registerPersistentGenerators(generators);
//				}
//			}
//		}
//
//		for (Collection collection : collections.values()) {
//			if (collection.isIdentified()) {
//				IdentifierGenerator ig = ((IdentifierCollection) collection)
//						.getIdentifier().createIdentifierGenerator(
//								getIdentifierGeneratorFactory(), dialect,
//								defaultCatalog, defaultSchema, null);
//
//				if (ig instanceof PersistentIdentifierGenerator) {
//					generators
//							.put(((PersistentIdentifierGenerator) ig)
//									.generatorKey(), ig);
//				}
//			}
//		}
//
//		return generators.values().iterator();
//	}
//
//	/**
//	 * Generate DDL for dropping tables
//	 * 
//	 * @param dialect
//	 *            The dialect for which to generate the drop script
//	 * 
//	 * @return The sequence of DDL commands to drop the schema objects
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates a problem calling
//	 *             {@link #buildMappings()}
//	 * 
//	 * @see org.hibernate.tool.hbm2ddl.SchemaExport
//	 */
//	public String[] generateDropSchemaScript(Dialect dialect)
//			throws HibernateException {
//		secondPassCompile();
//
//		String defaultCatalog = properties
//				.getProperty(Environment.DEFAULT_CATALOG);
//		String defaultSchema = properties
//				.getProperty(Environment.DEFAULT_SCHEMA);
//
//		ArrayList<String> script = new ArrayList<String>(50);
//
//		// drop them in reverse order in case db needs it done that way...
//		{
//			ListIterator itr = auxiliaryDatabaseObjects
//					.listIterator(auxiliaryDatabaseObjects.size());
//			while (itr.hasPrevious()) {
//				AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr
//						.previous();
//				if (object.appliesToDialect(dialect)) {
//					script.add(object.sqlDropString(dialect, defaultCatalog,
//							defaultSchema));
//				}
//			}
//		}
//
//		if (dialect.dropConstraints()) {
//			Iterator itr = getTableMappings();
//			while (itr.hasNext()) {
//				Table table = (Table) itr.next();
//				if (table.isPhysicalTable()) {
//					Iterator subItr = table.getForeignKeyIterator();
//					while (subItr.hasNext()) {
//						ForeignKey fk = (ForeignKey) subItr.next();
//						if (fk.isPhysicalConstraint()) {
//							script.add(fk.sqlDropString(dialect,
//									defaultCatalog, defaultSchema));
//						}
//					}
//				}
//			}
//		}
//
//		Iterator itr = getTableMappings();
//		while (itr.hasNext()) {
//
//			Table table = (Table) itr.next();
//			if (table.isPhysicalTable()) {
//
//				/*
//				 * Iterator subIter = table.getIndexIterator(); while (
//				 * subIter.hasNext() ) { Index index = (Index) subIter.next();
//				 * if ( !index.isForeignKey() ||
//				 * !dialect.hasImplicitIndexForForeignKey() ) { script.add(
//				 * index.sqlDropString(dialect) ); } }
//				 */
//
//				script.add(table.sqlDropString(dialect, defaultCatalog,
//						defaultSchema));
//
//			}
//
//		}
//
//		itr = iterateGenerators(dialect);
//		while (itr.hasNext()) {
//			String[] lines = ((PersistentIdentifierGenerator) itr.next())
//					.sqlDropStrings(dialect);
//			script.addAll(Arrays.asList(lines));
//		}
//
//		return ArrayHelper.toStringArray(script);
//	}
//
//	/**
//	 * @param dialect
//	 *            The dialect for which to generate the creation script
//	 * 
//	 * @return The sequence of DDL commands to create the schema objects
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates a problem calling
//	 *             {@link #buildMappings()}
//	 * 
//	 * @see org.hibernate.tool.hbm2ddl.SchemaExport
//	 */
//	@SuppressWarnings({ "unchecked" })
//	public String[] generateSchemaCreationScript(Dialect dialect)
//			throws HibernateException {
//		secondPassCompile();
//
//		ArrayList<String> script = new ArrayList<String>(50);
//		String defaultCatalog = properties
//				.getProperty(Environment.DEFAULT_CATALOG);
//		String defaultSchema = properties
//				.getProperty(Environment.DEFAULT_SCHEMA);
//
//		Iterator iter = getTableMappings();
//		while (iter.hasNext()) {
//			Table table = (Table) iter.next();
//			if (table.isPhysicalTable()) {
//				script.add(table.sqlCreateString(dialect, mapping,
//						defaultCatalog, defaultSchema));
//				Iterator<String> comments = table.sqlCommentStrings(dialect,
//						defaultCatalog, defaultSchema);
//				while (comments.hasNext()) {
//					script.add(comments.next());
//				}
//			}
//		}
//
//		iter = getTableMappings();
//		while (iter.hasNext()) {
//			Table table = (Table) iter.next();
//			if (table.isPhysicalTable()) {
//
//				if (!dialect.supportsUniqueConstraintInCreateAlterTable()) {
//					Iterator subIter = table.getUniqueKeyIterator();
//					while (subIter.hasNext()) {
//						UniqueKey uk = (UniqueKey) subIter.next();
//						String constraintString = uk.sqlCreateString(dialect,
//								mapping, defaultCatalog, defaultSchema);
//						if (constraintString != null)
//							script.add(constraintString);
//					}
//				}
//
//				Iterator subIter = table.getIndexIterator();
//				while (subIter.hasNext()) {
//					Index index = (Index) subIter.next();
//					script.add(index.sqlCreateString(dialect, mapping,
//							defaultCatalog, defaultSchema));
//				}
//
//				if (dialect.hasAlterTable()) {
//					subIter = table.getForeignKeyIterator();
//					while (subIter.hasNext()) {
//						ForeignKey fk = (ForeignKey) subIter.next();
//						if (fk.isPhysicalConstraint()) {
//							script.add(fk.sqlCreateString(dialect, mapping,
//									defaultCatalog, defaultSchema));
//						}
//					}
//				}
//
//			}
//		}
//
//		iter = iterateGenerators(dialect);
//		while (iter.hasNext()) {
//			String[] lines = ((PersistentIdentifierGenerator) iter.next())
//					.sqlCreateStrings(dialect);
//			script.addAll(Arrays.asList(lines));
//		}
//
//		for (AuxiliaryDatabaseObject auxiliaryDatabaseObject : auxiliaryDatabaseObjects) {
//			if (auxiliaryDatabaseObject.appliesToDialect(dialect)) {
//				script.add(auxiliaryDatabaseObject.sqlCreateString(dialect,
//						mapping, defaultCatalog, defaultSchema));
//			}
//		}
//
//		return ArrayHelper.toStringArray(script);
//	}
//
//	/**
//	 * @param dialect
//	 *            The dialect for which to generate the creation script
//	 * @param databaseMetadata
//	 *            The database catalog information for the database to be
//	 *            updated; needed to work out what should be created/altered
//	 * 
//	 * @return The sequence of DDL commands to apply the schema objects
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates a problem calling
//	 *             {@link #buildMappings()}
//	 * 
//	 * @see org.hibernate.tool.hbm2ddl.SchemaExport
//	 */
//	@SuppressWarnings({ "unchecked" })
//	public String[] generateSchemaUpdateScript(Dialect dialect,
//			DatabaseMetadata databaseMetadata) throws HibernateException {
//		secondPassCompile();
//
//		String defaultCatalog = properties
//				.getProperty(Environment.DEFAULT_CATALOG);
//		String defaultSchema = properties
//				.getProperty(Environment.DEFAULT_SCHEMA);
//
//		ArrayList<String> script = new ArrayList<String>(50);
//
//		Iterator iter = getTableMappings();
//		while (iter.hasNext()) {
//			Table table = (Table) iter.next();
//			if (table.isPhysicalTable()) {
//
//				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
//						table.getName(),
//						(table.getSchema() == null) ? defaultSchema : table
//								.getSchema(),
//						(table.getCatalog() == null) ? defaultCatalog : table
//								.getCatalog(), table.isQuoted()
//
//				);
//				if (tableInfo == null) {
//					script.add(table.sqlCreateString(dialect, mapping,
//							defaultCatalog, defaultSchema));
//				} else {
//					Iterator<String> subiter = table.sqlAlterStrings(dialect,
//							mapping, tableInfo, defaultCatalog, defaultSchema);
//					while (subiter.hasNext()) {
//						script.add(subiter.next());
//					}
//				}
//
//				Iterator<String> comments = table.sqlCommentStrings(dialect,
//						defaultCatalog, defaultSchema);
//				while (comments.hasNext()) {
//					script.add(comments.next());
//				}
//
//			}
//		}
//
//		iter = getTableMappings();
//		while (iter.hasNext()) {
//			Table table = (Table) iter.next();
//			if (table.isPhysicalTable()) {
//
//				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
//						table.getName(), table.getSchema(), table.getCatalog(),
//						table.isQuoted());
//
//				if (dialect.hasAlterTable()) {
//					Iterator subIter = table.getForeignKeyIterator();
//					while (subIter.hasNext()) {
//						ForeignKey fk = (ForeignKey) subIter.next();
//						if (fk.isPhysicalConstraint()) {
//							boolean create = tableInfo == null
//									|| (tableInfo.getForeignKeyMetadata(fk) == null && (
//									// Icky workaround for MySQL bug:
//									!(dialect instanceof MySQLDialect) || tableInfo
//											.getIndexMetadata(fk.getName()) == null));
//							if (create) {
//								script.add(fk.sqlCreateString(dialect, mapping,
//										defaultCatalog, defaultSchema));
//							}
//						}
//					}
//				}
//
//				Iterator subIter = table.getIndexIterator();
//				while (subIter.hasNext()) {
//					final Index index = (Index) subIter.next();
//					// Skip if index already exists
//					if (tableInfo != null
//							&& StringHelper.isNotEmpty(index.getName())) {
//						final IndexMetadata meta = tableInfo
//								.getIndexMetadata(index.getName());
//						if (meta != null) {
//							continue;
//						}
//					}
//					script.add(index.sqlCreateString(dialect, mapping,
//							defaultCatalog, defaultSchema));
//				}
//
//				// broken, 'cos we don't generate these with names in
//				// SchemaExport
//				// subIter = table.getUniqueKeyIterator();
//				// while ( subIter.hasNext() ) {
//				// UniqueKey uk = (UniqueKey) subIter.next();
//				// if ( tableInfo==null || tableInfo.getIndexMetadata(
//				// uk.getFilterName() ) == null ) {
//				// script.add( uk.sqlCreateString(dialect, mapping) );
//				// }
//				// }
//			}
//		}
//
//		iter = iterateGenerators(dialect);
//		while (iter.hasNext()) {
//			PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter
//					.next();
//			Object key = generator.generatorKey();
//			if (!databaseMetadata.isSequence(key)
//					&& !databaseMetadata.isTable(key)) {
//				String[] lines = generator.sqlCreateStrings(dialect);
//				script.addAll(Arrays.asList(lines));
//			}
//		}
//
//		return ArrayHelper.toStringArray(script);
//	}
//
//	public void validateSchema(Dialect dialect,
//			DatabaseMetadata databaseMetadata) throws HibernateException {
//		secondPassCompile();
//
//		String defaultCatalog = properties
//				.getProperty(Environment.DEFAULT_CATALOG);
//		String defaultSchema = properties
//				.getProperty(Environment.DEFAULT_SCHEMA);
//
//		Iterator iter = getTableMappings();
//		while (iter.hasNext()) {
//			Table table = (Table) iter.next();
//			if (table.isPhysicalTable()) {
//
//				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
//						table.getName(),
//						(table.getSchema() == null) ? defaultSchema : table
//								.getSchema(),
//						(table.getCatalog() == null) ? defaultCatalog : table
//								.getCatalog(), table.isQuoted());
//				if (tableInfo == null) {
//					throw new HibernateException("Missing table: "
//							+ table.getName());
//				} else {
//					table.validateColumns(dialect, mapping, tableInfo);
//				}
//
//			}
//		}
//
//		iter = iterateGenerators(dialect);
//		while (iter.hasNext()) {
//			PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter
//					.next();
//			Object key = generator.generatorKey();
//			if (!databaseMetadata.isSequence(key)
//					&& !databaseMetadata.isTable(key)) {
//				throw new HibernateException("Missing sequence or table: "
//						+ key);
//			}
//		}
//	}
//
//	private void validate() throws MappingException {
//		Iterator iter = classes.values().iterator();
//		while (iter.hasNext()) {
//			((PersistentClass) iter.next()).validate(mapping);
//		}
//		iter = collections.values().iterator();
//		while (iter.hasNext()) {
//			((Collection) iter.next()).validate(mapping);
//		}
//	}
//
//	/**
//	 * Call this to ensure the mappings are fully compiled/built. Usefull to
//	 * ensure getting access to all information in the metamodel when calling
//	 * e.g. getClassMappings().
//	 */
//	public void buildMappings() {
//		secondPassCompile();
//	}
//
//	protected void secondPassCompile() throws MappingException {
//		log.trace("Starting secondPassCompile() processing");
//
//		// process default values first
//		{
//			if (!isDefaultProcessed) {
//				// use global delimiters if orm.xml declare it
//				final Object isDelimited = reflectionManager.getDefaults().get(
//						"delimited-identifier");
//				if (isDelimited != null && isDelimited == Boolean.TRUE) {
//					getProperties().put(
//							Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true");
//				}
//
//				AnnotationBinder.bindDefaults(createMappings());
//				isDefaultProcessed = true;
//			}
//		}
//
//		// process metadata queue
//		{
//			metadataSourceQueue.syncAnnotatedClasses();
//			metadataSourceQueue
//					.processMetadata(determineMetadataSourcePrecedence());
//		}
//
//		// process cache queue
//		{
//			for (CacheHolder holder : caches) {
//				if (holder.isClass) {
//					applyCacheConcurrencyStrategy(holder);
//				} else {
//					applyCollectionCacheConcurrencyStrategy(holder);
//				}
//			}
//			caches.clear();
//		}
//
//		try {
//			inSecondPass = true;
//			processSecondPassesOfType(PkDrivenByDefaultMapsIdSecondPass.class);
//			processSecondPassesOfType(SetSimpleValueTypeSecondPass.class);
//			processSecondPassesOfType(CopyIdentifierComponentSecondPass.class);
//			processFkSecondPassInOrder();
//			processSecondPassesOfType(CreateKeySecondPass.class);
//			processSecondPassesOfType(SecondaryTableSecondPass.class);
//
//			originalSecondPassCompile();
//
//			inSecondPass = false;
//		} catch (RecoverableException e) {
//			// the exception was not recoverable after all
//			throw (RuntimeException) e.getCause();
//		}
//
//		for (Map.Entry<Table, List<UniqueConstraintHolder>> tableListEntry : uniqueConstraintHoldersByTable
//				.entrySet()) {
//			final Table table = tableListEntry.getKey();
//			final List<UniqueConstraintHolder> uniqueConstraints = tableListEntry
//					.getValue();
//			int uniqueIndexPerTable = 0;
//			for (UniqueConstraintHolder holder : uniqueConstraints) {
//				uniqueIndexPerTable++;
//				final String keyName = StringHelper.isEmpty(holder.getName()) ? "key"
//						+ uniqueIndexPerTable
//						: holder.getName();
//				buildUniqueKeyFromColumnNames(table, keyName,
//						holder.getColumns());
//			}
//		}
//
//		applyConstraintsToDDL();
//	}
//
//	private void processSecondPassesOfType(Class<? extends SecondPass> type) {
//		Iterator iter = secondPasses.iterator();
//		while (iter.hasNext()) {
//			SecondPass sp = (SecondPass) iter.next();
//			// do the second pass of simple value types first and remove them
//			if (type.isInstance(sp)) {
//				sp.doSecondPass(classes);
//				iter.remove();
//			}
//		}
//	}
//
//	/**
//	 * Processes FKSecondPass instances trying to resolve any graph circularity
//	 * (ie PK made of a many to one linking to an entity having a PK made of a
//	 * ManyToOne ...).
//	 */
//	private void processFkSecondPassInOrder() {
//		log.debug("processing fk mappings (*ToOne and JoinedSubclass)");
//		List<FkSecondPass> fkSecondPasses = getFKSecondPassesOnly();
//
//		if (fkSecondPasses.size() == 0) {
//			return; // nothing to do here
//		}
//
//		// split FkSecondPass instances into primary key and non primary key
//		// FKs.
//		// While doing so build a map of class names to FkSecondPass instances
//		// depending on this class.
//		Map<String, Set<FkSecondPass>> isADependencyOf = new HashMap<String, Set<FkSecondPass>>();
//		List<FkSecondPass> endOfQueueFkSecondPasses = new ArrayList<FkSecondPass>(
//				fkSecondPasses.size());
//		for (FkSecondPass sp : fkSecondPasses) {
//			if (sp.isInPrimaryKey()) {
//				String referenceEntityName = sp.getReferencedEntityName();
//				PersistentClass classMapping = getClassMapping(referenceEntityName);
//				String dependentTable = classMapping.getTable().getQuotedName();
//				if (!isADependencyOf.containsKey(dependentTable)) {
//					isADependencyOf.put(dependentTable,
//							new HashSet<FkSecondPass>());
//				}
//				isADependencyOf.get(dependentTable).add(sp);
//			} else {
//				endOfQueueFkSecondPasses.add(sp);
//			}
//		}
//
//		// using the isADependencyOf map we order the FkSecondPass recursively
//		// instances into the right order for processing
//		List<FkSecondPass> orderedFkSecondPasses = new ArrayList<FkSecondPass>(
//				fkSecondPasses.size());
//		for (String tableName : isADependencyOf.keySet()) {
//			buildRecursiveOrderedFkSecondPasses(orderedFkSecondPasses,
//					isADependencyOf, tableName, tableName);
//		}
//
//		// process the ordered FkSecondPasses
//		for (FkSecondPass sp : orderedFkSecondPasses) {
//			sp.doSecondPass(classes);
//		}
//
//		processEndOfQueue(endOfQueueFkSecondPasses);
//	}
//
//	/**
//	 * @return Returns a list of all <code>secondPasses</code> instances which
//	 *         are a instance of <code>FkSecondPass</code>.
//	 */
//	private List<FkSecondPass> getFKSecondPassesOnly() {
//		Iterator iter = secondPasses.iterator();
//		List<FkSecondPass> fkSecondPasses = new ArrayList<FkSecondPass>(
//				secondPasses.size());
//		while (iter.hasNext()) {
//			SecondPass sp = (SecondPass) iter.next();
//			// do the second pass of fk before the others and remove them
//			if (sp instanceof FkSecondPass) {
//				fkSecondPasses.add((FkSecondPass) sp);
//				iter.remove();
//			}
//		}
//		return fkSecondPasses;
//	}
//
//	/**
//	 * Recursively builds a list of FkSecondPass instances ready to be processed
//	 * in this order. Checking all dependencies recursively seems quite
//	 * expensive, but the original code just relied on some sort of table name
//	 * sorting which failed in certain circumstances.
//	 * <p/>
//	 * See <tt>ANN-722</tt> and <tt>ANN-730</tt>
//	 * 
//	 * @param orderedFkSecondPasses
//	 *            The list containing the
//	 *            <code>FkSecondPass<code> instances ready
//	 * for processing.
//	 * @param isADependencyOf
//	 *            Our lookup data structure to determine dependencies between
//	 *            tables
//	 * @param startTable
//	 *            Table name to start recursive algorithm.
//	 * @param currentTable
//	 *            The current table name used to check for 'new' dependencies.
//	 */
//	private void buildRecursiveOrderedFkSecondPasses(
//			List<FkSecondPass> orderedFkSecondPasses,
//			Map<String, Set<FkSecondPass>> isADependencyOf, String startTable,
//			String currentTable) {
//
//		Set<FkSecondPass> dependencies = isADependencyOf.get(currentTable);
//
//		// bottom out
//		if (dependencies == null || dependencies.size() == 0) {
//			return;
//		}
//
//		for (FkSecondPass sp : dependencies) {
//			String dependentTable = sp.getValue().getTable().getQuotedName();
//			if (dependentTable.compareTo(startTable) == 0) {
//				StringBuilder sb = new StringBuilder(
//						"Foreign key circularity dependency involving the following tables: ");
//				throw new AnnotationException(sb.toString());
//			}
//			buildRecursiveOrderedFkSecondPasses(orderedFkSecondPasses,
//					isADependencyOf, startTable, dependentTable);
//			if (!orderedFkSecondPasses.contains(sp)) {
//				orderedFkSecondPasses.add(0, sp);
//			}
//		}
//	}
//
//	private void processEndOfQueue(List<FkSecondPass> endOfQueueFkSecondPasses) {
//		/*
//		 * If a second pass raises a recoverableException, queue it for next
//		 * round stop of no pass has to be processed or if the number of pass to
//		 * processes does not diminish between two rounds. If some failing pass
//		 * remain, raise the original exception
//		 */
//		boolean stopProcess = false;
//		RuntimeException originalException = null;
//		while (!stopProcess) {
//			List<FkSecondPass> failingSecondPasses = new ArrayList<FkSecondPass>();
//			Iterator<FkSecondPass> it = endOfQueueFkSecondPasses.listIterator();
//			while (it.hasNext()) {
//				final FkSecondPass pass = it.next();
//				try {
//					pass.doSecondPass(classes);
//				} catch (RecoverableException e) {
//					failingSecondPasses.add(pass);
//					if (originalException == null) {
//						originalException = (RuntimeException) e.getCause();
//					}
//				}
//			}
//			stopProcess = failingSecondPasses.size() == 0
//					|| failingSecondPasses.size() == endOfQueueFkSecondPasses
//							.size();
//			endOfQueueFkSecondPasses = failingSecondPasses;
//		}
//		if (endOfQueueFkSecondPasses.size() > 0) {
//			throw originalException;
//		}
//	}
//
//	private void buildUniqueKeyFromColumnNames(Table table, String keyName,
//			String[] columnNames) {
//		keyName = normalizer.normalizeIdentifierQuoting(keyName);
//
//		UniqueKey uc;
//		int size = columnNames.length;
//		Column[] columns = new Column[size];
//		Set<Column> unbound = new HashSet<Column>();
//		Set<Column> unboundNoLogical = new HashSet<Column>();
//		for (int index = 0; index < size; index++) {
//			final String logicalColumnName = normalizer
//					.normalizeIdentifierQuoting(columnNames[index]);
//			try {
//				final String columnName = createMappings()
//						.getPhysicalColumnName(logicalColumnName, table);
//				columns[index] = new Column(columnName);
//				unbound.add(columns[index]);
//				// column equals and hashcode is based on column name
//			} catch (MappingException e) {
//				unboundNoLogical.add(new Column(logicalColumnName));
//			}
//		}
//		for (Column column : columns) {
//			if (table.containsColumn(column)) {
//				uc = table.getOrCreateUniqueKey(keyName);
//				uc.addColumn(table.getColumn(column));
//				unbound.remove(column);
//			}
//		}
//		if (unbound.size() > 0 || unboundNoLogical.size() > 0) {
//			StringBuilder sb = new StringBuilder(
//					"Unable to create unique key constraint (");
//			for (String columnName : columnNames) {
//				sb.append(columnName).append(", ");
//			}
//			sb.setLength(sb.length() - 2);
//			sb.append(") on table ").append(table.getName()).append(": ");
//			for (Column column : unbound) {
//				sb.append(column.getName()).append(", ");
//			}
//			for (Column column : unboundNoLogical) {
//				sb.append(column.getName()).append(", ");
//			}
//			sb.setLength(sb.length() - 2);
//			sb.append(" not found");
//			throw new AnnotationException(sb.toString());
//		}
//	}
//
//	private void applyConstraintsToDDL() {
//		boolean applyOnDdl = getProperties().getProperty(
//				"hibernate.validator.apply_to_ddl", "true").equalsIgnoreCase(
//				"true");
//
//		if (!applyOnDdl) {
//			return; // nothing to do in this case
//		}
//		applyHibernateValidatorLegacyConstraintsOnDDL();
//		applyBeanValidationConstraintsOnDDL();
//	}
//
//	@SuppressWarnings({ "unchecked" })
//	private void applyHibernateValidatorLegacyConstraintsOnDDL() {
//		// TODO search for the method only once and cache it?
//		Constructor validatorCtr = null;
//		Method applyMethod = null;
//		try {
//			Class classValidator = ReflectHelper.classForName(
//					"org.hibernate.validator.ClassValidator", this.getClass());
//			Class messageInterpolator = ReflectHelper.classForName(
//					"org.hibernate.validator.MessageInterpolator",
//					this.getClass());
//			validatorCtr = classValidator.getDeclaredConstructor(Class.class,
//					ResourceBundle.class, messageInterpolator, Map.class,
//					ReflectionManager.class);
//			applyMethod = classValidator.getMethod("apply",
//					PersistentClass.class);
//		} catch (ClassNotFoundException e) {
//			if (!isValidatorNotPresentLogged) {
//				log.info("Hibernate Validator not found: ignoring");
//			}
//			isValidatorNotPresentLogged = true;
//		} catch (NoSuchMethodException e) {
//			throw new AnnotationException(e);
//		}
//		if (applyMethod != null) {
//			for (PersistentClass persistentClazz : classes.values()) {
//				// integrate the validate framework
//				String className = persistentClazz.getClassName();
//				if (StringHelper.isNotEmpty(className)) {
//					try {
//						Object validator = validatorCtr.newInstance(
//								ReflectHelper.classForName(className), null,
//								null, null, reflectionManager);
//						applyMethod.invoke(validator, persistentClazz);
//					} catch (Exception e) {
//						log.warn("Unable to apply constraints on DDL for "
//								+ className, e);
//					}
//				}
//			}
//		}
//	}
//
//	@SuppressWarnings({ "unchecked" })
//	private void applyBeanValidationConstraintsOnDDL() {
//		BeanValidationActivator.applyDDL(classes.values(), getProperties());
//	}
//
//	private void originalSecondPassCompile() throws MappingException {
//		log.debug("processing extends queue");
//		processExtendsQueue();
//
//		log.debug("processing collection mappings");
//		Iterator itr = secondPasses.iterator();
//		while (itr.hasNext()) {
//			SecondPass sp = (SecondPass) itr.next();
//			if (!(sp instanceof QuerySecondPass)) {
//				sp.doSecondPass(classes);
//				itr.remove();
//			}
//		}
//
//		log.debug("processing native query and ResultSetMapping mappings");
//		itr = secondPasses.iterator();
//		while (itr.hasNext()) {
//			SecondPass sp = (SecondPass) itr.next();
//			sp.doSecondPass(classes);
//			itr.remove();
//		}
//
//		log.debug("processing association property references");
//
//		itr = propertyReferences.iterator();
//		while (itr.hasNext()) {
//			Mappings.PropertyReference upr = (Mappings.PropertyReference) itr
//					.next();
//
//			PersistentClass clazz = getClassMapping(upr.referencedClass);
//			if (clazz == null) {
//				throw new MappingException("property-ref to unmapped class: "
//						+ upr.referencedClass);
//			}
//
//			Property prop = clazz.getReferencedProperty(upr.propertyName);
//			if (upr.unique) {
//				((SimpleValue) prop.getValue()).setAlternateUniqueKey(true);
//			}
//		}
//
//		// TODO: Somehow add the newly created foreign keys to the internal
//		// collection
//
//		log.debug("processing foreign key constraints");
//
//		itr = getTableMappings();
//		Set done = new HashSet();
//		while (itr.hasNext()) {
//			secondPassCompileForeignKeys((Table) itr.next(), done);
//		}
//
//	}
//
//	private int processExtendsQueue() {
//		log.debug("processing extends queue");
//		int added = 0;
//		ExtendsQueueEntry extendsQueueEntry = findPossibleExtends();
//		while (extendsQueueEntry != null) {
//			metadataSourceQueue.processHbmXml(
//					extendsQueueEntry.getMetadataXml(),
//					extendsQueueEntry.getEntityNames());
//			extendsQueueEntry = findPossibleExtends();
//		}
//
//		if (extendsQueue.size() > 0) {
//			Iterator iterator = extendsQueue.keySet().iterator();
//			StringBuffer buf = new StringBuffer(
//					"Following super classes referenced in extends not found: ");
//			while (iterator.hasNext()) {
//				final ExtendsQueueEntry entry = (ExtendsQueueEntry) iterator
//						.next();
//				buf.append(entry.getExplicitName());
//				if (entry.getMappingPackage() != null) {
//					buf.append("[").append(entry.getMappingPackage())
//							.append("]");
//				}
//				if (iterator.hasNext()) {
//					buf.append(",");
//				}
//			}
//			throw new MappingException(buf.toString());
//		}
//
//		return added;
//	}
//
//	protected ExtendsQueueEntry findPossibleExtends() {
//		Iterator<ExtendsQueueEntry> itr = extendsQueue.keySet().iterator();
//		while (itr.hasNext()) {
//			final ExtendsQueueEntry entry = itr.next();
//			boolean found = getClassMapping(entry.getExplicitName()) != null
//					|| getClassMapping(HbmBinder.getClassName(
//							entry.getExplicitName(), entry.getMappingPackage())) != null;
//			if (found) {
//				itr.remove();
//				return entry;
//			}
//		}
//		return null;
//	}
//
//	protected void secondPassCompileForeignKeys(Table table, Set done)
//			throws MappingException {
//		table.createForeignKeys();
//		Iterator iter = table.getForeignKeyIterator();
//		while (iter.hasNext()) {
//
//			ForeignKey fk = (ForeignKey) iter.next();
//			if (!done.contains(fk)) {
//				done.add(fk);
//				final String referencedEntityName = fk
//						.getReferencedEntityName();
//				if (referencedEntityName == null) {
//					throw new MappingException("An association from the table "
//							+ fk.getTable().getName()
//							+ " does not specify the referenced entity");
//				}
//				if (log.isDebugEnabled()) {
//					log.debug("resolving reference to class: "
//							+ referencedEntityName);
//				}
//				PersistentClass referencedClass = classes
//						.get(referencedEntityName);
//				if (referencedClass == null) {
//					throw new MappingException("An association from the table "
//							+ fk.getTable().getName()
//							+ " refers to an unmapped class: "
//							+ referencedEntityName);
//				}
//				if (referencedClass.isJoinedSubclass()) {
//					secondPassCompileForeignKeys(referencedClass
//							.getSuperclass().getTable(), done);
//				}
//				fk.setReferencedTable(referencedClass.getTable());
//				fk.alignColumns();
//			}
//		}
//	}
//
//	public Map<String, NamedQueryDefinition> getNamedQueries() {
//		return namedQueries;
//	}
//
//	/**
//	 * Create a {@link SessionFactory} using the properties and mappings in this
//	 * MyConfiguration. The {@link SessionFactory} will be immutable, so changes
//	 * made to {@code this} {@link MyConfiguration} after building the
//	 * {@link SessionFactory} will not affect it.
//	 * 
//	 * @return The build {@link SessionFactory}
//	 * 
//	 * @throws HibernateException
//	 *             usually indicates an invalid MyConfiguration or invalid
//	 *             mapping information
//	 */
//	public SessionFactory buildSessionFactory() throws HibernateException {
//		log.debug("Preparing to build session factory with filters : "
//				+ filterDefinitions);
//
//		secondPassCompile();
//		if (!metadataSourceQueue.isEmpty()) {
//			log.warn("mapping metadata cache was not completely processed");
//		}
//
//		enableLegacyHibernateValidator();
//		enableBeanValidation();
//		enableHibernateSearch();
//
//		validate();
//		Environment.verifyProperties(properties);
//		Properties copy = new Properties();
//		copy.putAll(properties);
//		PropertiesHelper.resolvePlaceHolders(copy);
//		Settings settings = buildSettings(copy);
//
//		return new SessionFactoryImpl(this, mapping, settings,
//				getInitializedEventListeners(), sessionFactoryObserver);
//	}
//
//	private static final String LEGACY_VALIDATOR_EVENT_LISTENER = "org.hibernate.validator.event.ValidateEventListener";
//
//	private void enableLegacyHibernateValidator() {
//		// add validator events if the jar is available
//		boolean enableValidatorListeners = !"false"
//				.equalsIgnoreCase(getProperty("hibernate.validator.autoregister_listeners"));
//		Class validateEventListenerClass = null;
//		try {
//			validateEventListenerClass = ReflectHelper.classForName(
//					LEGACY_VALIDATOR_EVENT_LISTENER, MyConfiguration.class);
//		} catch (ClassNotFoundException e) {
//			// validator is not present
//			log.debug("Legacy Validator not present in classpath, ignoring event listener registration");
//		}
//		if (enableValidatorListeners && validateEventListenerClass != null) {
//			// TODO so much duplication
//			Object validateEventListener;
//			try {
//				validateEventListener = validateEventListenerClass
//						.newInstance();
//			} catch (Exception e) {
//				throw new AnnotationException(
//						"Unable to load Validator event listener", e);
//			}
//			{
//				boolean present = false;
//				PreInsertEventListener[] listeners = getEventListeners()
//						.getPreInsertEventListeners();
//				if (listeners != null) {
//					for (Object eventListener : listeners) {
//						// not isAssignableFrom since the user could subclass
//						present = present
//								|| validateEventListenerClass == eventListener
//										.getClass();
//					}
//					if (!present) {
//						int length = listeners.length + 1;
//						PreInsertEventListener[] newListeners = new PreInsertEventListener[length];
//						System.arraycopy(listeners, 0, newListeners, 0,
//								length - 1);
//						newListeners[length - 1] = (PreInsertEventListener) validateEventListener;
//						getEventListeners().setPreInsertEventListeners(
//								newListeners);
//					}
//				} else {
//					getEventListeners()
//							.setPreInsertEventListeners(
//									new PreInsertEventListener[] { (PreInsertEventListener) validateEventListener });
//				}
//			}
//
//			// update event listener
//			{
//				boolean present = false;
//				PreUpdateEventListener[] listeners = getEventListeners()
//						.getPreUpdateEventListeners();
//				if (listeners != null) {
//					for (Object eventListener : listeners) {
//						// not isAssignableFrom since the user could subclass
//						present = present
//								|| validateEventListenerClass == eventListener
//										.getClass();
//					}
//					if (!present) {
//						int length = listeners.length + 1;
//						PreUpdateEventListener[] newListeners = new PreUpdateEventListener[length];
//						System.arraycopy(listeners, 0, newListeners, 0,
//								length - 1);
//						newListeners[length - 1] = (PreUpdateEventListener) validateEventListener;
//						getEventListeners().setPreUpdateEventListeners(
//								newListeners);
//					}
//				} else {
//					getEventListeners()
//							.setPreUpdateEventListeners(
//									new PreUpdateEventListener[] { (PreUpdateEventListener) validateEventListener });
//				}
//			}
//		}
//	}
//
//	private void enableBeanValidation() {
//		BeanValidationActivator.activateBeanValidation(getEventListeners(),
//				getProperties());
//	}
//
//	private static final String SEARCH_EVENT_LISTENER_REGISTERER_CLASS = "org.hibernate.cfg.search.HibernateSearchEventListenerRegister";
//
//	/**
//	 * Tries to automatically register Hibernate Search event listeners by
//	 * locating the appropriate bootstrap class and calling the
//	 * <code>enableHibernateSearch</code> method.
//	 */
//	private void enableHibernateSearch() {
//		// load the bootstrap class
//		Class searchStartupClass;
//		try {
//			searchStartupClass = ReflectHelper.classForName(
//					SEARCH_STARTUP_CLASS, getClass());
//		} catch (ClassNotFoundException e) {
//			// TODO remove this together with SearchMyConfiguration after 3.1.0
//			// release of Search
//			// try loading deprecated HibernateSearchEventListenerRegister
//			try {
//				searchStartupClass = ReflectHelper.classForName(
//						SEARCH_EVENT_LISTENER_REGISTERER_CLASS, getClass());
//			} catch (ClassNotFoundException cnfe) {
//				log.debug("Search not present in classpath, ignoring event listener registration.");
//				return;
//			}
//		}
//
//		// call the method for registering the listeners
//		try {
//			Object searchStartupInstance = searchStartupClass.newInstance();
//			Method enableSearchMethod = searchStartupClass.getDeclaredMethod(
//					SEARCH_STARTUP_METHOD, EventListeners.class,
//					Properties.class);
//			enableSearchMethod.invoke(searchStartupInstance,
//					getEventListeners(), getProperties());
//		} catch (InstantiationException e) {
//			log.debug(
//					"Unable to instantiate {}, ignoring event listener registration.",
//					SEARCH_STARTUP_CLASS);
//		} catch (IllegalAccessException e) {
//			log.debug(
//					"Unable to instantiate {}, ignoring event listener registration.",
//					SEARCH_STARTUP_CLASS);
//		} catch (NoSuchMethodException e) {
//			log.debug("Method enableHibernateSearch() not found in {}.",
//					SEARCH_STARTUP_CLASS);
//		} catch (InvocationTargetException e) {
//			log.debug(
//					"Unable to execute {}, ignoring event listener registration.",
//					SEARCH_STARTUP_METHOD);
//		}
//	}
//
//	private EventListeners getInitializedEventListeners() {
//		EventListeners result = (EventListeners) eventListeners.shallowCopy();
//		result.initializeListeners(this);
//		return result;
//	}
//
//	/**
//	 * Rterieve the configured {@link Interceptor}.
//	 * 
//	 * @return The current {@link Interceptor}
//	 */
//	public Interceptor getInterceptor() {
//		return interceptor;
//	}
//
//	/**
//	 * Set the current {@link Interceptor}
//	 * 
//	 * @param interceptor
//	 *            The {@link Interceptor} to use for the
//	 *            {@link #buildSessionFactory() built} {@link SessionFactory}.
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setInterceptor(Interceptor interceptor) {
//		this.interceptor = interceptor;
//		return this;
//	}
//
//	/**
//	 * Get all properties
//	 * 
//	 * @return all properties
//	 */
//	public Properties getProperties() {
//		return properties;
//	}
//
//	/**
//	 * Get a property value by name
//	 * 
//	 * @param propertyName
//	 *            The name of the property
//	 * 
//	 * @return The value curently associated with that property name; may be
//	 *         null.
//	 */
//	public String getProperty(String propertyName) {
//		return properties.getProperty(propertyName);
//	}
//
//	/**
//	 * Specify a completely new set of properties
//	 * 
//	 * @param properties
//	 *            The new set of properties
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setProperties(Properties properties) {
//		this.properties = properties;
//		return this;
//	}
//
//	/**
//	 * Add the given properties to ours.
//	 * 
//	 * @param extraProperties
//	 *            The properties to add.
//	 * 
//	 * @return this for method chaining
//	 * 
//	 */
//	public MyConfiguration addProperties(Properties extraProperties) {
//		this.properties.putAll(extraProperties);
//		return this;
//	}
//
//	/**
//	 * Adds the incoming properties to the internal properties structure, as
//	 * long as the internal structure does not already contain an entry for the
//	 * given key.
//	 * 
//	 * @param properties
//	 *            The properties to merge
//	 * 
//	 * @return this for ethod chaining
//	 */
//	public MyConfiguration mergeProperties(Properties properties) {
//		for (Map.Entry entry : properties.entrySet()) {
//			if (this.properties.containsKey(entry.getKey())) {
//				continue;
//			}
//			this.properties.setProperty((String) entry.getKey(),
//					(String) entry.getValue());
//		}
//		return this;
//	}
//
//	/**
//	 * Set a property value by name
//	 * 
//	 * @param propertyName
//	 *            The name of the property to set
//	 * @param value
//	 *            The new property value
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setProperty(String propertyName, String value) {
//		properties.setProperty(propertyName, value);
//		return this;
//	}
//
//	private void addProperties(Element parent) {
//		Iterator itr = parent.elementIterator("property");
//		while (itr.hasNext()) {
//			Element node = (Element) itr.next();
//			String name = node.attributeValue("name");
//			String value = node.getText().trim();
//			log.debug(name + "=" + value);
//			properties.setProperty(name, value);
//			if (!name.startsWith("hibernate")) {
//				properties.setProperty("hibernate." + name, value);
//			}
//		}
//		Environment.verifyProperties(properties);
//	}
//
//	/**
//	 * Use the mappings and properties specified in an application resource
//	 * named <tt>hibernate.cfg.xml</tt>.
//	 * 
//	 * @return this for method chaining
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates we cannot find <tt>hibernate.cfg.xml</tt>
//	 * 
//	 * @see #configure(String)
//	 */
//	public MyConfiguration configure() throws HibernateException {
//		configure("/hibernate.cfg.xml");
//		return this;
//	}
//
//	/**
//	 * Use the mappings and properties specified in the given application
//	 * resource. The format of the resource is defined in
//	 * <tt>hibernate-MyConfiguration-3.0.dtd</tt>.
//	 * <p/>
//	 * The resource is found via {@link #getMyConfigurationInputStream}
//	 * 
//	 * @param resource
//	 *            The resource to use
//	 * 
//	 * @return this for method chaining
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates we cannot find the named resource
//	 * 
//	 * @see #doConfigure(java.io.InputStream, String)
//	 */
//	public MyConfiguration configure(String resource) throws HibernateException {
//		log.info("configuring from resource: " + resource);
//		InputStream stream = getMyConfigurationInputStream(resource);
//		return doConfigure(stream, resource);
//	}
//
//	/**
//	 * Get the MyConfiguration file as an <tt>InputStream</tt>. Might be
//	 * overridden by subclasses to allow the MyConfiguration to be located by
//	 * some arbitrary mechanism.
//	 * <p/>
//	 * By default here we use classpath resource resolution
//	 * 
//	 * @param resource
//	 *            The resource to locate
//	 * 
//	 * @return The stream
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates we cannot find the named resource
//	 */
//	protected InputStream getMyConfigurationInputStream(String resource)
//			throws HibernateException {
//		log.info("MyConfiguration resource: " + resource);
//		return ConfigHelper.getResourceAsStream(resource);
//	}
//
//	/**
//	 * Use the mappings and properties specified in the given document. The
//	 * format of the document is defined in
//	 * <tt>hibernate-MyConfiguration-3.0.dtd</tt>.
//	 * 
//	 * @param url
//	 *            URL from which you wish to load the MyConfiguration
//	 * 
//	 * @return this for method chaining
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates a problem access the url
//	 * 
//	 * @see #doConfigure(java.io.InputStream, String)
//	 */
//	public MyConfiguration configure(URL url) throws HibernateException {
//		log.info("configuring from url: " + url.toString());
//		try {
//			return doConfigure(url.openStream(), url.toString());
//		} catch (IOException ioe) {
//			throw new HibernateException(
//					"could not configure from URL: " + url, ioe);
//		}
//	}
//
//	/**
//	 * Use the mappings and properties specified in the given application file.
//	 * The format of the file is defined in
//	 * <tt>hibernate-MyConfiguration-3.0.dtd</tt>.
//	 * 
//	 * @param configFile
//	 *            File from which you wish to load the MyConfiguration
//	 * 
//	 * @return this for method chaining
//	 * 
//	 * @throws HibernateException
//	 *             Generally indicates a problem access the file
//	 * 
//	 * @see #doConfigure(java.io.InputStream, String)
//	 */
//	public MyConfiguration configure(File configFile) throws HibernateException {
//		log.info("configuring from file: " + configFile.getName());
//		try {
//			return doConfigure(new FileInputStream(configFile),
//					configFile.toString());
//		} catch (FileNotFoundException fnfe) {
//			throw new HibernateException("could not find file: " + configFile,
//					fnfe);
//		}
//	}
//
//	/**
//	 * Configure this MyConfiguration's state from the contents of the given
//	 * input stream. The expectation is that the stream contents represent an
//	 * XML document conforming to the Hibernate MyConfiguration DTD. See
//	 * {@link #doConfigure(Document)} for further details.
//	 * 
//	 * @param stream
//	 *            The input stream from which to read
//	 * @param resourceName
//	 *            The name to use in warning/error messages
//	 * 
//	 * @return this for method chaining
//	 * 
//	 * @throws HibernateException
//	 *             Indicates a problem reading the stream contents.
//	 */
//	protected MyConfiguration doConfigure(InputStream stream,
//			String resourceName) throws HibernateException {
//		try {
//			List errors = new ArrayList();
//			Document document = xmlHelper.createSAXReader(resourceName, errors,
//					entityResolver).read(new InputSource(stream));
//			if (errors.size() != 0) {
//				throw new MappingException("invalid MyConfiguration",
//						(Throwable) errors.get(0));
//			}
//			doConfigure(document);
//		} catch (DocumentException e) {
//			throw new HibernateException("Could not parse MyConfiguration: "
//					+ resourceName, e);
//		} finally {
//			try {
//				stream.close();
//			} catch (IOException ioe) {
//				log.warn("could not close input stream for: " + resourceName,
//						ioe);
//			}
//		}
//		return this;
//	}
//
//	/**
//	 * Use the mappings and properties specified in the given XML document. The
//	 * format of the file is defined in
//	 * <tt>hibernate-MyConfiguration-3.0.dtd</tt>.
//	 * 
//	 * @param document
//	 *            an XML document from which you wish to load the
//	 *            MyConfiguration
//	 * @return A MyConfiguration configured via the <tt>Document</tt>
//	 * @throws HibernateException
//	 *             if there is problem in accessing the file.
//	 */
//	public MyConfiguration configure(org.w3c.dom.Document document)
//			throws HibernateException {
//		log.info("configuring from XML document");
//		return doConfigure(xmlHelper.createDOMReader().read(document));
//	}
//
//	/**
//	 * Parse a dom4j document conforming to the Hibernate MyConfiguration DTD (
//	 * <tt>hibernate-MyConfiguration-3.0.dtd</tt>) and use its information to
//	 * configure this {@link MyConfiguration}'s state
//	 * 
//	 * @param doc
//	 *            The dom4j document
//	 * 
//	 * @return this for method chaining
//	 * 
//	 * @throws HibernateException
//	 *             Indicates a problem performing the MyConfiguration task
//	 */
//	protected MyConfiguration doConfigure(Document doc)
//			throws HibernateException {
//		Element sfNode = doc.getRootElement().element("session-factory");
//		String name = sfNode.attributeValue("name");
//		if (name != null) {
//			properties.setProperty(Environment.SESSION_FACTORY_NAME, name);
//		}
//		addProperties(sfNode);
//		parseSessionFactory(sfNode, name);
//
//		Element secNode = doc.getRootElement().element("security");
//		if (secNode != null) {
//			parseSecurity(secNode);
//		}
//
//		log.info("Configured SessionFactory: " + name);
//		log.debug("properties: " + properties);
//
//		return this;
//	}
//
//	private void parseSessionFactory(Element sfNode, String name) {
//		Iterator elements = sfNode.elementIterator();
//		while (elements.hasNext()) {
//			Element subelement = (Element) elements.next();
//			String subelementName = subelement.getName();
//			if ("mapping".equals(subelementName)) {
//				parseMappingElement(subelement, name);
//			} else if ("class-cache".equals(subelementName)) {
//				String className = subelement.attributeValue("class");
//				Attribute regionNode = subelement.attribute("region");
//				final String region = (regionNode == null) ? className
//						: regionNode.getValue();
//				boolean includeLazy = !"non-lazy".equals(subelement
//						.attributeValue("include"));
//				setCacheConcurrencyStrategy(className,
//						subelement.attributeValue("usage"), region, includeLazy);
//			} else if ("collection-cache".equals(subelementName)) {
//				String role = subelement.attributeValue("collection");
//				Attribute regionNode = subelement.attribute("region");
//				final String region = (regionNode == null) ? role : regionNode
//						.getValue();
//				setCollectionCacheConcurrencyStrategy(role,
//						subelement.attributeValue("usage"), region);
//			} else if ("listener".equals(subelementName)) {
//				parseListener(subelement);
//			} else if ("event".equals(subelementName)) {
//				parseEvent(subelement);
//			}
//		}
//	}
//
//	private void parseMappingElement(Element mappingElement, String name) {
//		final Attribute resourceAttribute = mappingElement
//				.attribute("resource");
//		final Attribute fileAttribute = mappingElement.attribute("file");
//		final Attribute jarAttribute = mappingElement.attribute("jar");
//		final Attribute packageAttribute = mappingElement.attribute("package");
//		final Attribute classAttribute = mappingElement.attribute("class");
//
//		if (resourceAttribute != null) {
//			final String resourceName = resourceAttribute.getValue();
//			log.debug(
//					"session-factory config [{}] named resource [{}] for mapping",
//					name, resourceName);
//			addResource(resourceName);
//		} else if (fileAttribute != null) {
//			final String fileName = fileAttribute.getValue();
//			log.debug(
//					"session-factory config [{}] named file [{}] for mapping",
//					name, fileName);
//			addFile(fileName);
//		} else if (jarAttribute != null) {
//			final String jarFileName = jarAttribute.getValue();
//			log.debug(
//					"session-factory config [{}] named jar file [{}] for mapping",
//					name, jarFileName);
//			addJar(new File(jarFileName));
//		} else if (packageAttribute != null) {
//			final String packageName = packageAttribute.getValue();
//			log.debug(
//					"session-factory config [{}] named package [{}] for mapping",
//					name, packageName);
//			addPackage(packageName);
//		} else if (classAttribute != null) {
//			final String className = classAttribute.getValue();
//			log.debug(
//					"session-factory config [{}] named class [{}] for mapping",
//					name, className);
//
//			try {
//				addAnnotatedClass(ReflectHelper.classForName(className));
//			} catch (Exception e) {
//				throw new MappingException(
//						"Unable to load class [ "
//								+ className
//								+ "] declared in Hibernate MyConfiguration <mapping/> entry",
//						e);
//			}
//		} else {
//			throw new MappingException(
//					"<mapping> element in MyConfiguration specifies no known attributes");
//		}
//	}
//
//	private void parseSecurity(Element secNode) {
//		String contextId = secNode.attributeValue("context");
//		setProperty(Environment.JACC_CONTEXTID, contextId);
//		log.info("JACC contextID: " + contextId);
//		JACCMyConfiguration jcfg = new JACCMyConfiguration(contextId);
//		Iterator grantElements = secNode.elementIterator();
//		while (grantElements.hasNext()) {
//			Element grantElement = (Element) grantElements.next();
//			String elementName = grantElement.getName();
//			if ("grant".equals(elementName)) {
//				jcfg.addPermission(grantElement.attributeValue("role"),
//						grantElement.attributeValue("entity-name"),
//						grantElement.attributeValue("actions"));
//			}
//		}
//	}
//
//	private void parseEvent(Element element) {
//		String type = element.attributeValue("type");
//		List listeners = element.elements();
//		String[] listenerClasses = new String[listeners.size()];
//		for (int i = 0; i < listeners.size(); i++) {
//			listenerClasses[i] = ((Element) listeners.get(i))
//					.attributeValue("class");
//		}
//		log.debug("Event listeners: " + type + "="
//				+ StringHelper.toString(listenerClasses));
//		setListeners(type, listenerClasses);
//	}
//
//	private void parseListener(Element element) {
//		String type = element.attributeValue("type");
//		if (type == null) {
//			throw new MappingException("No type specified for listener");
//		}
//		String impl = element.attributeValue("class");
//		log.debug("Event listener: " + type + "=" + impl);
//		setListeners(type, new String[] { impl });
//	}
//
//	public void setListener(String type, String listener) {
//		String[] listeners = null;
//		if (listener != null) {
//			listeners = (String[]) Array.newInstance(String.class, 1);
//			listeners[0] = listener;
//		}
//		setListeners(type, listeners);
//	}
//
//	public void setListeners(String type, String[] listenerClasses) {
//		Object[] listeners = null;
//		if (listenerClasses != null) {
//			listeners = (Object[]) Array.newInstance(
//					eventListeners.getListenerClassFor(type),
//					listenerClasses.length);
//			for (int i = 0; i < listeners.length; i++) {
//				try {
//					listeners[i] = ReflectHelper.classForName(
//							listenerClasses[i]).newInstance();
//				} catch (Exception e) {
//					throw new MappingException(
//							"Unable to instantiate specified event (" + type
//									+ ") listener class: " + listenerClasses[i],
//							e);
//				}
//			}
//		}
//		setListeners(type, listeners);
//	}
//
//	public void setListener(String type, Object listener) {
//		Object[] listeners = null;
//		if (listener != null) {
//			listeners = (Object[]) Array.newInstance(
//					eventListeners.getListenerClassFor(type), 1);
//			listeners[0] = listener;
//		}
//		setListeners(type, listeners);
//	}
//
//	public void setListeners(String type, Object[] listeners) {
//		if ("auto-flush".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setAutoFlushEventListeners(new AutoFlushEventListener[] {});
//			} else {
//				eventListeners
//						.setAutoFlushEventListeners((AutoFlushEventListener[]) listeners);
//			}
//		} else if ("merge".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setMergeEventListeners(new MergeEventListener[] {});
//			} else {
//				eventListeners
//						.setMergeEventListeners((MergeEventListener[]) listeners);
//			}
//		} else if ("create".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPersistEventListeners(new PersistEventListener[] {});
//			} else {
//				eventListeners
//						.setPersistEventListeners((PersistEventListener[]) listeners);
//			}
//		} else if ("create-onflush".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPersistOnFlushEventListeners(new PersistEventListener[] {});
//			} else {
//				eventListeners
//						.setPersistOnFlushEventListeners((PersistEventListener[]) listeners);
//			}
//		} else if ("delete".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setDeleteEventListeners(new DeleteEventListener[] {});
//			} else {
//				eventListeners
//						.setDeleteEventListeners((DeleteEventListener[]) listeners);
//			}
//		} else if ("dirty-check".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setDirtyCheckEventListeners(new DirtyCheckEventListener[] {});
//			} else {
//				eventListeners
//						.setDirtyCheckEventListeners((DirtyCheckEventListener[]) listeners);
//			}
//		} else if ("evict".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setEvictEventListeners(new EvictEventListener[] {});
//			} else {
//				eventListeners
//						.setEvictEventListeners((EvictEventListener[]) listeners);
//			}
//		} else if ("flush".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setFlushEventListeners(new FlushEventListener[] {});
//			} else {
//				eventListeners
//						.setFlushEventListeners((FlushEventListener[]) listeners);
//			}
//		} else if ("flush-entity".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setFlushEntityEventListeners(new FlushEntityEventListener[] {});
//			} else {
//				eventListeners
//						.setFlushEntityEventListeners((FlushEntityEventListener[]) listeners);
//			}
//		} else if ("load".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setLoadEventListeners(new LoadEventListener[] {});
//			} else {
//				eventListeners
//						.setLoadEventListeners((LoadEventListener[]) listeners);
//			}
//		} else if ("load-collection".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setInitializeCollectionEventListeners(new InitializeCollectionEventListener[] {});
//			} else {
//				eventListeners
//						.setInitializeCollectionEventListeners((InitializeCollectionEventListener[]) listeners);
//			}
//		} else if ("lock".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setLockEventListeners(new LockEventListener[] {});
//			} else {
//				eventListeners
//						.setLockEventListeners((LockEventListener[]) listeners);
//			}
//		} else if ("refresh".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setRefreshEventListeners(new RefreshEventListener[] {});
//			} else {
//				eventListeners
//						.setRefreshEventListeners((RefreshEventListener[]) listeners);
//			}
//		} else if ("replicate".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setReplicateEventListeners(new ReplicateEventListener[] {});
//			} else {
//				eventListeners
//						.setReplicateEventListeners((ReplicateEventListener[]) listeners);
//			}
//		} else if ("save-update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setSaveOrUpdateEventListeners(new SaveOrUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setSaveOrUpdateEventListeners((SaveOrUpdateEventListener[]) listeners);
//			}
//		} else if ("save".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setSaveEventListeners(new SaveOrUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setSaveEventListeners((SaveOrUpdateEventListener[]) listeners);
//			}
//		} else if ("update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setUpdateEventListeners(new SaveOrUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setUpdateEventListeners((SaveOrUpdateEventListener[]) listeners);
//			}
//		} else if ("pre-load".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreLoadEventListeners(new PreLoadEventListener[] {});
//			} else {
//				eventListeners
//						.setPreLoadEventListeners((PreLoadEventListener[]) listeners);
//			}
//		} else if ("pre-update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreUpdateEventListeners(new PreUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setPreUpdateEventListeners((PreUpdateEventListener[]) listeners);
//			}
//		} else if ("pre-delete".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreDeleteEventListeners(new PreDeleteEventListener[] {});
//			} else {
//				eventListeners
//						.setPreDeleteEventListeners((PreDeleteEventListener[]) listeners);
//			}
//		} else if ("pre-insert".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreInsertEventListeners(new PreInsertEventListener[] {});
//			} else {
//				eventListeners
//						.setPreInsertEventListeners((PreInsertEventListener[]) listeners);
//			}
//		} else if ("pre-collection-recreate".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreCollectionRecreateEventListeners(new PreCollectionRecreateEventListener[] {});
//			} else {
//				eventListeners
//						.setPreCollectionRecreateEventListeners((PreCollectionRecreateEventListener[]) listeners);
//			}
//		} else if ("pre-collection-remove".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreCollectionRemoveEventListeners(new PreCollectionRemoveEventListener[] {});
//			} else {
//				eventListeners
//						.setPreCollectionRemoveEventListeners((PreCollectionRemoveEventListener[]) listeners);
//			}
//		} else if ("pre-collection-update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPreCollectionUpdateEventListeners(new PreCollectionUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setPreCollectionUpdateEventListeners((PreCollectionUpdateEventListener[]) listeners);
//			}
//		} else if ("post-load".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostLoadEventListeners(new PostLoadEventListener[] {});
//			} else {
//				eventListeners
//						.setPostLoadEventListeners((PostLoadEventListener[]) listeners);
//			}
//		} else if ("post-update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostUpdateEventListeners(new PostUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setPostUpdateEventListeners((PostUpdateEventListener[]) listeners);
//			}
//		} else if ("post-delete".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostDeleteEventListeners(new PostDeleteEventListener[] {});
//			} else {
//				eventListeners
//						.setPostDeleteEventListeners((PostDeleteEventListener[]) listeners);
//			}
//		} else if ("post-insert".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostInsertEventListeners(new PostInsertEventListener[] {});
//			} else {
//				eventListeners
//						.setPostInsertEventListeners((PostInsertEventListener[]) listeners);
//			}
//		} else if ("post-commit-update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostCommitUpdateEventListeners(new PostUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setPostCommitUpdateEventListeners((PostUpdateEventListener[]) listeners);
//			}
//		} else if ("post-commit-delete".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostCommitDeleteEventListeners(new PostDeleteEventListener[] {});
//			} else {
//				eventListeners
//						.setPostCommitDeleteEventListeners((PostDeleteEventListener[]) listeners);
//			}
//		} else if ("post-commit-insert".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostCommitInsertEventListeners(new PostInsertEventListener[] {});
//			} else {
//				eventListeners
//						.setPostCommitInsertEventListeners((PostInsertEventListener[]) listeners);
//			}
//		} else if ("post-collection-recreate".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostCollectionRecreateEventListeners(new PostCollectionRecreateEventListener[] {});
//			} else {
//				eventListeners
//						.setPostCollectionRecreateEventListeners((PostCollectionRecreateEventListener[]) listeners);
//			}
//		} else if ("post-collection-remove".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostCollectionRemoveEventListeners(new PostCollectionRemoveEventListener[] {});
//			} else {
//				eventListeners
//						.setPostCollectionRemoveEventListeners((PostCollectionRemoveEventListener[]) listeners);
//			}
//		} else if ("post-collection-update".equals(type)) {
//			if (listeners == null) {
//				eventListeners
//						.setPostCollectionUpdateEventListeners(new PostCollectionUpdateEventListener[] {});
//			} else {
//				eventListeners
//						.setPostCollectionUpdateEventListeners((PostCollectionUpdateEventListener[]) listeners);
//			}
//		} else {
//			throw new MappingException("Unrecognized listener type [" + type
//					+ "]");
//		}
//	}
//
//	public EventListeners getEventListeners() {
//		return eventListeners;
//	}
//
//	RootClass getRootClassMapping(String clazz) throws MappingException {
//		try {
//			return (RootClass) getClassMapping(clazz);
//		} catch (ClassCastException cce) {
//			throw new MappingException(
//					"You may only specify a cache for root <class> mappings");
//		}
//	}
//
//	/**
//	 * Set up a cache for an entity class
//	 * 
//	 * @param entityName
//	 *            The name of the entity to which we shoudl associate these
//	 *            cache settings
//	 * @param concurrencyStrategy
//	 *            The cache strategy to use
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setCacheConcurrencyStrategy(String entityName,
//			String concurrencyStrategy) {
//		setCacheConcurrencyStrategy(entityName, concurrencyStrategy, entityName);
//		return this;
//	}
//
//	/**
//	 * Set up a cache for an entity class, giving an explicit region name
//	 * 
//	 * @param entityName
//	 *            The name of the entity to which we should associate these
//	 *            cache settings
//	 * @param concurrencyStrategy
//	 *            The cache strategy to use
//	 * @param region
//	 *            The name of the cache region to use
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setCacheConcurrencyStrategy(String entityName,
//			String concurrencyStrategy, String region) {
//		setCacheConcurrencyStrategy(entityName, concurrencyStrategy, region,
//				true);
//		return this;
//	}
//
//	public void setCacheConcurrencyStrategy(String entityName,
//			String concurrencyStrategy, String region, boolean cacheLazyProperty)
//			throws MappingException {
//		caches.add(new CacheHolder(entityName, concurrencyStrategy, region,
//				true, cacheLazyProperty));
//	}
//
//	private void applyCacheConcurrencyStrategy(CacheHolder holder) {
//		RootClass rootClass = getRootClassMapping(holder.role);
//		if (rootClass == null) {
//			throw new MappingException("Cannot cache an unknown entity: "
//					+ holder.role);
//		}
//		rootClass.setCacheConcurrencyStrategy(holder.usage);
//		rootClass.setCacheRegionName(holder.region);
//		rootClass.setLazyPropertiesCacheable(holder.cacheLazy);
//	}
//
//	/**
//	 * Set up a cache for a collection role
//	 * 
//	 * @param collectionRole
//	 *            The name of the collection to which we should associate these
//	 *            cache settings
//	 * @param concurrencyStrategy
//	 *            The cache strategy to use
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setCollectionCacheConcurrencyStrategy(
//			String collectionRole, String concurrencyStrategy) {
//		setCollectionCacheConcurrencyStrategy(collectionRole,
//				concurrencyStrategy, collectionRole);
//		return this;
//	}
//
//	/**
//	 * Set up a cache for a collection role, giving an explicit region name
//	 * 
//	 * @param collectionRole
//	 *            The name of the collection to which we should associate these
//	 *            cache settings
//	 * @param concurrencyStrategy
//	 *            The cache strategy to use
//	 * @param region
//	 *            The name of the cache region to use
//	 * 
//	 * @return this for method chaining
//	 */
//	public void setCollectionCacheConcurrencyStrategy(String collectionRole,
//			String concurrencyStrategy, String region) {
//		caches.add(new CacheHolder(collectionRole, concurrencyStrategy, region,
//				false, false));
//	}
//
//	private void applyCollectionCacheConcurrencyStrategy(CacheHolder holder) {
//		Collection collection = getCollectionMapping(holder.role);
//		if (collection == null) {
//			throw new MappingException("Cannot cache an unknown collection: "
//					+ holder.role);
//		}
//		collection.setCacheConcurrencyStrategy(holder.usage);
//		collection.setCacheRegionName(holder.region);
//	}
//
//	/**
//	 * Get the query language imports
//	 * 
//	 * @return a mapping from "import" names to fully qualified class names
//	 */
//	public Map<String, String> getImports() {
//		return imports;
//	}
//
//	/**
//	 * Create an object-oriented view of the MyConfiguration properties
//	 * 
//	 * @return The build settings
//	 */
//	public Settings buildSettings() {
//		Properties clone = (Properties) properties.clone();
//		PropertiesHelper.resolvePlaceHolders(clone);
//		return buildSettingsInternal(clone);
//	}
//
//	public Settings buildSettings(Properties props) throws HibernateException {
//		return buildSettingsInternal(props);
//	}
//
//	private Settings buildSettingsInternal(Properties props) {
//		final Settings settings = settingsFactory.buildSettings(props);
//		settings.setEntityTuplizerFactory(this.getEntityTuplizerFactory());
//		// settings.setComponentTuplizerFactory(
//		// this.getComponentTuplizerFactory() );
//		return settings;
//	}
//
//	public Map getNamedSQLQueries() {
//		return namedSqlQueries;
//	}
//
//	public Map getSqlResultSetMappings() {
//		return sqlResultSetMappings;
//	}
//
//	public NamingStrategy getNamingStrategy() {
//		return namingStrategy;
//	}
//
//	/**
//	 * Set a custom naming strategy
//	 * 
//	 * @param namingStrategy
//	 *            the NamingStrategy to set
//	 * 
//	 * @return this for method chaining
//	 */
//	public MyConfiguration setNamingStrategy(NamingStrategy namingStrategy) {
//		this.namingStrategy = namingStrategy;
//		return this;
//	}
//
//	public PersisterClassProvider getPersisterClassProvider() {
//		return persisterClassProvider;
//	}
//
//	/**
//	 * Defines a custom persister class provider.
//	 * 
//	 * The persister class is chosen according to the following rules in
//	 * decreasing priority: - the persister class defined explicitly via
//	 * annotation or XML - the persister class returned by the
//	 * PersisterClassProvider implementation (if not null) - the default
//	 * provider as chosen by Hibernate Core (best choice most of the time)
//	 * 
//	 * 
//	 * @param persisterClassProvider
//	 *            implementation
//	 */
//	public MyConfiguration setPersisterClassProvider(
//			PersisterClassProvider persisterClassProvider) {
//		this.persisterClassProvider = persisterClassProvider;
//		return this;
//	}
//
//	/**
//	 * Retrieve the IdentifierGeneratorFactory in effect for this
//	 * MyConfiguration.
//	 * 
//	 * @return This MyConfiguration's IdentifierGeneratorFactory.
//	 */
//	public DefaultIdentifierGeneratorFactory getIdentifierGeneratorFactory() {
//		return identifierGeneratorFactory;
//	}
//
//	public Mapping buildMapping() {
//		return new Mapping() {
//			public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
//				return identifierGeneratorFactory;
//			}
//
//			/**
//			 * Returns the identifier type of a mapped class
//			 */
//			public Type getIdentifierType(String entityName)
//					throws MappingException {
//				PersistentClass pc = classes.get(entityName);
//				if (pc == null) {
//					throw new MappingException("persistent class not known: "
//							+ entityName);
//				}
//				return pc.getIdentifier().getType();
//			}
//
//			public String getIdentifierPropertyName(String entityName)
//					throws MappingException {
//				final PersistentClass pc = classes.get(entityName);
//				if (pc == null) {
//					throw new MappingException("persistent class not known: "
//							+ entityName);
//				}
//				if (!pc.hasIdentifierProperty()) {
//					return null;
//				}
//				return pc.getIdentifierProperty().getName();
//			}
//
//			public Type getReferencedPropertyType(String entityName,
//					String propertyName) throws MappingException {
//				final PersistentClass pc = classes.get(entityName);
//				if (pc == null) {
//					throw new MappingException("persistent class not known: "
//							+ entityName);
//				}
//				Property prop = pc.getReferencedProperty(propertyName);
//				if (prop == null) {
//					throw new MappingException("property not known: "
//							+ entityName + '.' + propertyName);
//				}
//				return prop.getType();
//			}
//		};
//	}
//
//	private void readObject(ObjectInputStream ois) throws IOException,
//			ClassNotFoundException {
//		// we need reflectionManager before reading the other components
//		// (MetadataSourceQueue in particular)
//		final MetadataProvider metadataProvider = (MetadataProvider) ois
//				.readObject();
//		this.mapping = buildMapping();
//		xmlHelper = new XMLHelper();
//		createReflectionManager(metadataProvider);
//		ois.defaultReadObject();
//	}
//
//	private void writeObject(java.io.ObjectOutputStream out) throws IOException {
//		// We write MetadataProvider first as we need reflectionManager before
//		// reading the other components
//		final MetadataProvider metadataProvider = ((MetadataProviderInjector) reflectionManager)
//				.getMetadataProvider();
//		out.writeObject(metadataProvider);
//		out.defaultWriteObject();
//	}
//
//	private void createReflectionManager() {
//		createReflectionManager(new JPAMetadataProvider());
//	}
//
//	private void createReflectionManager(MetadataProvider metadataProvider) {
//		reflectionManager = new JavaReflectionManager();
//		((MetadataProviderInjector) reflectionManager)
//				.setMetadataProvider(metadataProvider);
//	}
//
//	public Map getFilterDefinitions() {
//		return filterDefinitions;
//	}
//
//	public void addFilterDefinition(FilterDefinition definition) {
//		filterDefinitions.put(definition.getFilterName(), definition);
//	}
//
//	public Iterator iterateFetchProfiles() {
//		return fetchProfiles.values().iterator();
//	}
//
//	public void addFetchProfile(FetchProfile fetchProfile) {
//		fetchProfiles.put(fetchProfile.getName(), fetchProfile);
//	}
//
//	public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) {
//		auxiliaryDatabaseObjects.add(object);
//	}
//
//	public Map getSqlFunctions() {
//		return sqlFunctions;
//	}
//
//	public void addSqlFunction(String functionName, SQLFunction function) {
//		sqlFunctions.put(functionName, function);
//	}
//
//	public TypeResolver getTypeResolver() {
//		return typeResolver;
//	}
//
//	/**
//	 * Allows registration of a type into the type registry. The phrase
//	 * 'override' in the method name simply reminds that registration
//	 * *potentially* replaces a previously registered type .
//	 * 
//	 * @param type
//	 *            The type to register.
//	 */
//	public void registerTypeOverride(BasicType type) {
//		getTypeResolver().registerTypeOverride(type);
//	}
//
//	public void registerTypeOverride(UserType type, String[] keys) {
//		getTypeResolver().registerTypeOverride(type, keys);
//	}
//
//	public void registerTypeOverride(CompositeUserType type, String[] keys) {
//		getTypeResolver().registerTypeOverride(type, keys);
//	}
//
//	public SessionFactoryObserver getSessionFactoryObserver() {
//		return sessionFactoryObserver;
//	}
//
//	public void setSessionFactoryObserver(
//			SessionFactoryObserver sessionFactoryObserver) {
//		this.sessionFactoryObserver = sessionFactoryObserver;
//	}
//
//	// Mappings impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//	/**
//	 * Internal implementation of the Mappings interface giving access to the
//	 * MyConfiguration's internal <tt>metadata repository</tt> state (
//	 * {@link MyConfiguration#classes}, {@link MyConfiguration#tables}, etc).
//	 */
//	protected class MappingsImpl implements ExtendedMappings, Serializable {
//
//		private String schemaName;
//
//		public String getSchemaName() {
//			return schemaName;
//		}
//
//		public void setSchemaName(String schemaName) {
//			this.schemaName = schemaName;
//		}
//
//		private String catalogName;
//
//		public String getCatalogName() {
//			return catalogName;
//		}
//
//		public void setCatalogName(String catalogName) {
//			this.catalogName = catalogName;
//		}
//
//		private String defaultPackage;
//
//		public String getDefaultPackage() {
//			return defaultPackage;
//		}
//
//		public void setDefaultPackage(String defaultPackage) {
//			this.defaultPackage = defaultPackage;
//		}
//
//		private boolean autoImport;
//
//		public boolean isAutoImport() {
//			return autoImport;
//		}
//
//		public void setAutoImport(boolean autoImport) {
//			this.autoImport = autoImport;
//		}
//
//		private boolean defaultLazy;
//
//		public boolean isDefaultLazy() {
//			return defaultLazy;
//		}
//
//		public void setDefaultLazy(boolean defaultLazy) {
//			this.defaultLazy = defaultLazy;
//		}
//
//		private String defaultCascade;
//
//		public String getDefaultCascade() {
//			return defaultCascade;
//		}
//
//		public void setDefaultCascade(String defaultCascade) {
//			this.defaultCascade = defaultCascade;
//		}
//
//		private String defaultAccess;
//
//		public String getDefaultAccess() {
//			return defaultAccess;
//		}
//
//		public void setDefaultAccess(String defaultAccess) {
//			this.defaultAccess = defaultAccess;
//		}
//
//		public NamingStrategy getNamingStrategy() {
//			return namingStrategy;
//		}
//
//		public void setNamingStrategy(NamingStrategy namingStrategy) {
//			MyConfiguration.this.namingStrategy = namingStrategy;
//		}
//
//		public PersisterClassProvider getPersisterClassProvider() {
//			return persisterClassProvider;
//		}
//
//		public void setPersisterClassProvider(
//				PersisterClassProvider persisterClassProvider) {
//			MyConfiguration.this.persisterClassProvider = persisterClassProvider;
//		}
//
//		public TypeResolver getTypeResolver() {
//			return typeResolver;
//		}
//
//		public Iterator<PersistentClass> iterateClasses() {
//			return classes.values().iterator();
//		}
//
//		public PersistentClass getClass(String entityName) {
//			return classes.get(entityName);
//		}
//
//		public PersistentClass locatePersistentClassByEntityName(
//				String entityName) {
//			PersistentClass persistentClass = classes.get(entityName);
//			if (persistentClass == null) {
//				String actualEntityName = imports.get(entityName);
//				if (StringHelper.isNotEmpty(actualEntityName)) {
//					persistentClass = classes.get(actualEntityName);
//				}
//			}
//			return persistentClass;
//		}
//
//		public void addClass(PersistentClass persistentClass)
//				throws DuplicateMappingException {
//			Object old = classes.put(persistentClass.getEntityName(),
//					persistentClass);
//			if (old != null) {
//				throw new DuplicateMappingException("class/entity",
//						persistentClass.getEntityName());
//			}
//		}
//
//		public void addImport(String entityName, String rename)
//				throws DuplicateMappingException {
//			String existing = imports.put(rename, entityName);
//			if (existing != null) {
//				if (existing.equals(entityName)) {
//					log.info("duplicate import: {} -> {}", entityName, rename);
//				} else {
//					throw new DuplicateMappingException("duplicate import: "
//							+ rename + " refers to both " + entityName
//							+ " and " + existing
//							+ " (try using auto-import=\"false\")", "import",
//							rename);
//				}
//			}
//		}
//
//		public Collection getCollection(String role) {
//			return collections.get(role);
//		}
//
//		public Iterator<Collection> iterateCollections() {
//			return collections.values().iterator();
//		}
//
//		public void addCollection(Collection collection)
//				throws DuplicateMappingException {
//			Object old = collections.put(collection.getRole(), collection);
//			if (old != null) {
//				throw new DuplicateMappingException("collection role",
//						collection.getRole());
//			}
//		}
//
//		public Table getTable(String schema, String catalog, String name) {
//			String key = Table.qualify(catalog, schema, name);
//			return tables.get(key);
//		}
//
//		public Iterator<Table> iterateTables() {
//			return tables.values().iterator();
//		}
//
//		public Table addTable(String schema, String catalog, String name,
//				String subselect, boolean isAbstract) {
//			name = getObjectNameNormalizer().normalizeIdentifierQuoting(name);
//			schema = getObjectNameNormalizer().normalizeIdentifierQuoting(
//					schema);
//			catalog = getObjectNameNormalizer().normalizeIdentifierQuoting(
//					catalog);
//
//			String key = subselect == null ? Table.qualify(catalog, schema,
//					name) : subselect;
//			Table table = tables.get(key);
//
//			if (table == null) {
//				table = new Table();
//				table.setAbstract(isAbstract);
//				table.setName(name);
//				table.setSchema(schema);
//				table.setCatalog(catalog);
//				table.setSubselect(subselect);
//				tables.put(key, table);
//			} else {
//				if (!isAbstract) {
//					table.setAbstract(false);
//				}
//			}
//
//			return table;
//		}
//
//		public Table addDenormalizedTable(String schema, String catalog,
//				String name, boolean isAbstract, String subselect,
//				Table includedTable) throws DuplicateMappingException {
//			name = getObjectNameNormalizer().normalizeIdentifierQuoting(name);
//			schema = getObjectNameNormalizer().normalizeIdentifierQuoting(
//					schema);
//			catalog = getObjectNameNormalizer().normalizeIdentifierQuoting(
//					catalog);
//
//			String key = subselect == null ? Table.qualify(catalog, schema,
//					name) : subselect;
//			if (tables.containsKey(key)) {
//				throw new DuplicateMappingException("table", name);
//			}
//
//			Table table = new DenormalizedTable(includedTable);
//			table.setAbstract(isAbstract);
//			table.setName(name);
//			table.setSchema(schema);
//			table.setCatalog(catalog);
//			table.setSubselect(subselect);
//
//			tables.put(key, table);
//			return table;
//		}
//
//		public NamedQueryDefinition getQuery(String name) {
//			return namedQueries.get(name);
//		}
//
//		public void addQuery(String name, NamedQueryDefinition query)
//				throws DuplicateMappingException {
//			if (!defaultNamedQueryNames.contains(name)) {
//				applyQuery(name, query);
//			}
//		}
//
//		private void applyQuery(String name, NamedQueryDefinition query) {
//			checkQueryName(name);
//			namedQueries.put(name.intern(), query);
//		}
//
//		private void checkQueryName(String name)
//				throws DuplicateMappingException {
//			if (namedQueries.containsKey(name)
//					|| namedSqlQueries.containsKey(name)) {
//				throw new DuplicateMappingException("query", name);
//			}
//		}
//
//		public void addDefaultQuery(String name, NamedQueryDefinition query) {
//			applyQuery(name, query);
//			defaultNamedQueryNames.add(name);
//		}
//
//		public NamedSQLQueryDefinition getSQLQuery(String name) {
//			return namedSqlQueries.get(name);
//		}
//
//		public void addSQLQuery(String name, NamedSQLQueryDefinition query)
//				throws DuplicateMappingException {
//			if (!defaultNamedNativeQueryNames.contains(name)) {
//				applySQLQuery(name, query);
//			}
//		}
//
//		private void applySQLQuery(String name, NamedSQLQueryDefinition query)
//				throws DuplicateMappingException {
//			checkQueryName(name);
//			namedSqlQueries.put(name.intern(), query);
//		}
//
//		public void addDefaultSQLQuery(String name,
//				NamedSQLQueryDefinition query) {
//			applySQLQuery(name, query);
//			defaultNamedNativeQueryNames.add(name);
//		}
//
//		public ResultSetMappingDefinition getResultSetMapping(String name) {
//			return sqlResultSetMappings.get(name);
//		}
//
//		public void addResultSetMapping(
//				ResultSetMappingDefinition sqlResultSetMapping)
//				throws DuplicateMappingException {
//			if (!defaultSqlResultSetMappingNames.contains(sqlResultSetMapping
//					.getName())) {
//				applyResultSetMapping(sqlResultSetMapping);
//			}
//		}
//
//		public void applyResultSetMapping(
//				ResultSetMappingDefinition sqlResultSetMapping)
//				throws DuplicateMappingException {
//			Object old = sqlResultSetMappings.put(
//					sqlResultSetMapping.getName(), sqlResultSetMapping);
//			if (old != null) {
//				throw new DuplicateMappingException("resultSet",
//						sqlResultSetMapping.getName());
//			}
//		}
//
//		public void addDefaultResultSetMapping(
//				ResultSetMappingDefinition definition) {
//			final String name = definition.getName();
//			if (!defaultSqlResultSetMappingNames.contains(name)
//					&& getResultSetMapping(name) != null) {
//				removeResultSetMapping(name);
//			}
//			applyResultSetMapping(definition);
//			defaultSqlResultSetMappingNames.add(name);
//		}
//
//		protected void removeResultSetMapping(String name) {
//			sqlResultSetMappings.remove(name);
//		}
//
//		public TypeDef getTypeDef(String typeName) {
//			return typeDefs.get(typeName);
//		}
//
//		public void addTypeDef(String typeName, String typeClass,
//				Properties paramMap) {
//			TypeDef def = new TypeDef(typeClass, paramMap);
//			typeDefs.put(typeName, def);
//			log.debug("Added " + typeName + " with class " + typeClass);
//		}
//
//		public Map getFilterDefinitions() {
//			return filterDefinitions;
//		}
//
//		public FilterDefinition getFilterDefinition(String name) {
//			return filterDefinitions.get(name);
//		}
//
//		public void addFilterDefinition(FilterDefinition definition) {
//			filterDefinitions.put(definition.getFilterName(), definition);
//		}
//
//		public FetchProfile findOrCreateFetchProfile(String name,
//				MetadataSource source) {
//			FetchProfile profile = fetchProfiles.get(name);
//			if (profile == null) {
//				profile = new FetchProfile(name, source);
//				fetchProfiles.put(name, profile);
//			}
//			return profile;
//		}
//
//		public Iterator<AuxiliaryDatabaseObject> iterateAuxliaryDatabaseObjects() {
//			return iterateAuxiliaryDatabaseObjects();
//		}
//
//		public Iterator<AuxiliaryDatabaseObject> iterateAuxiliaryDatabaseObjects() {
//			return auxiliaryDatabaseObjects.iterator();
//		}
//
//		public ListIterator<AuxiliaryDatabaseObject> iterateAuxliaryDatabaseObjectsInReverse() {
//			return iterateAuxiliaryDatabaseObjectsInReverse();
//		}
//
//		public ListIterator<AuxiliaryDatabaseObject> iterateAuxiliaryDatabaseObjectsInReverse() {
//			return auxiliaryDatabaseObjects
//					.listIterator(auxiliaryDatabaseObjects.size());
//		}
//
//		public void addAuxiliaryDatabaseObject(
//				AuxiliaryDatabaseObject auxiliaryDatabaseObject) {
//			auxiliaryDatabaseObjects.add(auxiliaryDatabaseObject);
//		}
//
//		/**
//		 * Internal struct used to help track physical table names to logical
//		 * table names.
//		 */
//		private class TableDescription implements Serializable {
//			final String logicalName;
//			final Table denormalizedSupertable;
//
//			TableDescription(String logicalName, Table denormalizedSupertable) {
//				this.logicalName = logicalName;
//				this.denormalizedSupertable = denormalizedSupertable;
//			}
//		}
//
//		public String getLogicalTableName(Table table) throws MappingException {
//			return getLogicalTableName(table.getQuotedSchema(),
//					table.getCatalog(), table.getQuotedName());
//		}
//
//		private String getLogicalTableName(String schema, String catalog,
//				String physicalName) throws MappingException {
//			String key = buildTableNameKey(schema, catalog, physicalName);
//			TableDescription descriptor = (TableDescription) tableNameBinding
//					.get(key);
//			if (descriptor == null) {
//				throw new MappingException("Unable to find physical table: "
//						+ physicalName);
//			}
//			return descriptor.logicalName;
//		}
//
//		public void addTableBinding(String schema, String catalog,
//				String logicalName, String physicalName,
//				Table denormalizedSuperTable) throws DuplicateMappingException {
//			String key = buildTableNameKey(schema, catalog, physicalName);
//			TableDescription tableDescription = new TableDescription(
//					logicalName, denormalizedSuperTable);
//			TableDescription oldDescriptor = (TableDescription) tableNameBinding
//					.put(key, tableDescription);
//			if (oldDescriptor != null
//					&& !oldDescriptor.logicalName.equals(logicalName)) {
//				// TODO possibly relax that
//				throw new DuplicateMappingException(
//						"Same physical table name [" + physicalName
//								+ "] references several logical table names: ["
//								+ oldDescriptor.logicalName + "], ["
//								+ logicalName + ']', "table", physicalName);
//			}
//		}
//
//		private String buildTableNameKey(String schema, String catalog,
//				String finalName) {
//			StringBuffer keyBuilder = new StringBuffer();
//			if (schema != null)
//				keyBuilder.append(schema);
//			keyBuilder.append(".");
//			if (catalog != null)
//				keyBuilder.append(catalog);
//			keyBuilder.append(".");
//			keyBuilder.append(finalName);
//			return keyBuilder.toString();
//		}
//
//		/**
//		 * Internal struct used to maintain xref between physical and logical
//		 * column names for a table. Mainly this is used to ensure that the
//		 * defined {@link NamingStrategy} is not creating duplicate column
//		 * names.
//		 */
//		private class TableColumnNameBinding implements Serializable {
//			private final String tableName;
//			private Map/* <String, String> */logicalToPhysical = new HashMap();
//			private Map/* <String, String> */physicalToLogical = new HashMap();
//
//			private TableColumnNameBinding(String tableName) {
//				this.tableName = tableName;
//			}
//
//			public void addBinding(String logicalName, Column physicalColumn) {
//				bindLogicalToPhysical(logicalName, physicalColumn);
//				bindPhysicalToLogical(logicalName, physicalColumn);
//			}
//
//			private void bindLogicalToPhysical(String logicalName,
//					Column physicalColumn) throws DuplicateMappingException {
//				final String logicalKey = logicalName.toLowerCase();
//				final String physicalName = physicalColumn.getQuotedName();
//				final String existingPhysicalName = (String) logicalToPhysical
//						.put(logicalKey, physicalName);
//				if (existingPhysicalName != null) {
//					boolean areSamePhysicalColumn = physicalColumn.isQuoted() ? existingPhysicalName
//							.equals(physicalName) : existingPhysicalName
//							.equalsIgnoreCase(physicalName);
//					if (!areSamePhysicalColumn) {
//						throw new DuplicateMappingException(
//								" Table ["
//										+ tableName
//										+ "] contains logical column name ["
//										+ logicalName
//										+ "] referenced by multiple physical column names: ["
//										+ existingPhysicalName + "], ["
//										+ physicalName + "]", "column-binding",
//								tableName + "." + logicalName);
//					}
//				}
//			}
//
//			private void bindPhysicalToLogical(String logicalName,
//					Column physicalColumn) throws DuplicateMappingException {
//				final String physicalName = physicalColumn.getQuotedName();
//				final String existingLogicalName = (String) physicalToLogical
//						.put(physicalName, logicalName);
//				if (existingLogicalName != null
//						&& !existingLogicalName.equals(logicalName)) {
//					throw new DuplicateMappingException(
//							" Table ["
//									+ tableName
//									+ "] contains phyical column name ["
//									+ physicalName
//									+ "] represented by different logical column names: ["
//									+ existingLogicalName + "], ["
//									+ logicalName + "]", "column-binding",
//							tableName + "." + physicalName);
//				}
//			}
//		}
//
//		public void addColumnBinding(String logicalName, Column physicalColumn,
//				Table table) throws DuplicateMappingException {
//			TableColumnNameBinding binding = (TableColumnNameBinding) columnNameBindingPerTable
//					.get(table);
//			if (binding == null) {
//				binding = new TableColumnNameBinding(table.getName());
//				columnNameBindingPerTable.put(table, binding);
//			}
//			binding.addBinding(logicalName, physicalColumn);
//		}
//
//		public String getPhysicalColumnName(String logicalName, Table table)
//				throws MappingException {
//			logicalName = logicalName.toLowerCase();
//			String finalName = null;
//			Table currentTable = table;
//			do {
//				TableColumnNameBinding binding = (TableColumnNameBinding) columnNameBindingPerTable
//						.get(currentTable);
//				if (binding != null) {
//					finalName = (String) binding.logicalToPhysical
//							.get(logicalName);
//				}
//				String key = buildTableNameKey(currentTable.getQuotedSchema(),
//						currentTable.getCatalog(), currentTable.getQuotedName());
//				TableDescription description = (TableDescription) tableNameBinding
//						.get(key);
//				if (description != null) {
//					currentTable = description.denormalizedSupertable;
//				} else {
//					currentTable = null;
//				}
//			} while (finalName == null && currentTable != null);
//
//			if (finalName == null) {
//				throw new MappingException(
//						"Unable to find column with logical name "
//								+ logicalName + " in table " + table.getName());
//			}
//			return finalName;
//		}
//
//		public String getLogicalColumnName(String physicalName, Table table)
//				throws MappingException {
//			String logical = null;
//			Table currentTable = table;
//			TableDescription description = null;
//			do {
//				TableColumnNameBinding binding = (TableColumnNameBinding) columnNameBindingPerTable
//						.get(currentTable);
//				if (binding != null) {
//					logical = (String) binding.physicalToLogical
//							.get(physicalName);
//				}
//				String key = buildTableNameKey(currentTable.getQuotedSchema(),
//						currentTable.getCatalog(), currentTable.getQuotedName());
//				description = (TableDescription) tableNameBinding.get(key);
//				if (description != null) {
//					currentTable = description.denormalizedSupertable;
//				} else {
//					currentTable = null;
//				}
//			} while (logical == null && currentTable != null
//					&& description != null);
//			if (logical == null) {
//				throw new MappingException(
//						"Unable to find logical column name from physical name "
//								+ physicalName + " in table " + table.getName());
//			}
//			return logical;
//		}
//
//		public void addSecondPass(SecondPass sp) {
//			addSecondPass(sp, false);
//		}
//
//		public void addSecondPass(SecondPass sp, boolean onTopOfTheQueue) {
//			if (onTopOfTheQueue) {
//				secondPasses.add(0, sp);
//			} else {
//				secondPasses.add(sp);
//			}
//		}
//
//		public void addPropertyReference(String referencedClass,
//				String propertyName) {
//			propertyReferences.add(new PropertyReference(referencedClass,
//					propertyName, false));
//		}
//
//		public void addUniquePropertyReference(String referencedClass,
//				String propertyName) {
//			propertyReferences.add(new PropertyReference(referencedClass,
//					propertyName, true));
//		}
//
//		public void addToExtendsQueue(ExtendsQueueEntry entry) {
//			extendsQueue.put(entry, null);
//		}
//
//		public DefaultIdentifierGeneratorFactory getIdentifierGeneratorFactory() {
//			return identifierGeneratorFactory;
//		}
//
//		public void addMappedSuperclass(Class type,
//				MappedSuperclass mappedSuperclass) {
//			mappedSuperClasses.put(type, mappedSuperclass);
//		}
//
//		public MappedSuperclass getMappedSuperclass(Class type) {
//			return mappedSuperClasses.get(type);
//		}
//
//		public ObjectNameNormalizer getObjectNameNormalizer() {
//			return normalizer;
//		}
//
//		public Properties getMyConfigurationProperties() {
//			return properties;
//		}
//
//		private Boolean useNewGeneratorMappings;
//
//		public void addDefaultGenerator(IdGenerator generator) {
//			this.addGenerator(generator);
//			defaultNamedGenerators.add(generator.getName());
//		}
//
//		public boolean isInSecondPass() {
//			return inSecondPass;
//		}
//
//		public PropertyData getPropertyAnnotatedWithMapsId(XClass entityType,
//				String propertyName) {
//			final Map<String, PropertyData> map = propertiesAnnotatedWithMapsId
//					.get(entityType);
//			return map == null ? null : map.get(propertyName);
//		}
//
//		public void addPropertyAnnotatedWithMapsId(XClass entityType,
//				PropertyData property) {
//			Map<String, PropertyData> map = propertiesAnnotatedWithMapsId
//					.get(entityType);
//			if (map == null) {
//				map = new HashMap<String, PropertyData>();
//				propertiesAnnotatedWithMapsId.put(entityType, map);
//			}
//			map.put(property.getProperty().getAnnotation(MapsId.class).value(),
//					property);
//		}
//
//		public boolean isSpecjProprietarySyntaxEnabled() {
//			return specjProprietarySyntaxEnabled;
//		}
//
//		public void addPropertyAnnotatedWithMapsIdSpecj(XClass entityType,
//				PropertyData property, String mapsIdValue) {
//			Map<String, PropertyData> map = propertiesAnnotatedWithMapsId
//					.get(entityType);
//			if (map == null) {
//				map = new HashMap<String, PropertyData>();
//				propertiesAnnotatedWithMapsId.put(entityType, map);
//			}
//			map.put(mapsIdValue, property);
//		}
//
//		public PropertyData getPropertyAnnotatedWithIdAndToOne(
//				XClass entityType, String propertyName) {
//			final Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne
//					.get(entityType);
//			return map == null ? null : map.get(propertyName);
//		}
//
//		public void addToOneAndIdProperty(XClass entityType,
//				PropertyData property) {
//			Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne
//					.get(entityType);
//			if (map == null) {
//				map = new HashMap<String, PropertyData>();
//				propertiesAnnotatedWithIdAndToOne.put(entityType, map);
//			}
//			map.put(property.getPropertyName(), property);
//		}
//
//		@SuppressWarnings({ "UnnecessaryUnboxing" })
//		public boolean useNewGeneratorMappings() {
//			if (useNewGeneratorMappings == null) {
//				final String booleanName = getMyConfigurationProperties()
//						.getProperty(USE_NEW_ID_GENERATOR_MAPPINGS);
//				useNewGeneratorMappings = Boolean.valueOf(booleanName);
//			}
//			return useNewGeneratorMappings.booleanValue();
//		}
//
//		public IdGenerator getGenerator(String name) {
//			return getGenerator(name, null);
//		}
//
//		public IdGenerator getGenerator(String name,
//				Map<String, IdGenerator> localGenerators) {
//			if (localGenerators != null) {
//				IdGenerator result = localGenerators.get(name);
//				if (result != null) {
//					return result;
//				}
//			}
//			return namedGenerators.get(name);
//		}
//
//		public void addGenerator(IdGenerator generator) {
//			if (!defaultNamedGenerators.contains(generator.getName())) {
//				IdGenerator old = namedGenerators.put(generator.getName(),
//						generator);
//				if (old != null) {
//					log.warn("duplicate generator name {}", old.getName());
//				}
//			}
//		}
//
//		public void addGeneratorTable(String name, Properties params) {
//			Object old = generatorTables.put(name, params);
//			if (old != null) {
//				log.warn("duplicate generator table: {}", name);
//			}
//		}
//
//		public Properties getGeneratorTableProperties(String name,
//				Map<String, Properties> localGeneratorTables) {
//			if (localGeneratorTables != null) {
//				Properties result = localGeneratorTables.get(name);
//				if (result != null) {
//					return result;
//				}
//			}
//			return generatorTables.get(name);
//		}
//
//		public Map<String, Join> getJoins(String entityName) {
//			return joins.get(entityName);
//		}
//
//		public void addJoins(PersistentClass persistentClass,
//				Map<String, Join> joins) {
//			Object old = MyConfiguration.this.joins.put(
//					persistentClass.getEntityName(), joins);
//			if (old != null) {
//				log.warn("duplicate joins for class: {}",
//						persistentClass.getEntityName());
//			}
//		}
//
//		public AnnotatedClassType getClassType(XClass clazz) {
//			AnnotatedClassType type = classTypes.get(clazz.getName());
//			if (type == null) {
//				return addClassType(clazz);
//			} else {
//				return type;
//			}
//		}
//
//		// FIXME should be private but is part of the ExtendedMapping contract
//
//		public AnnotatedClassType addClassType(XClass clazz) {
//			AnnotatedClassType type;
//			if (clazz.isAnnotationPresent(Entity.class)) {
//				type = AnnotatedClassType.ENTITY;
//			} else if (clazz.isAnnotationPresent(Embeddable.class)) {
//				type = AnnotatedClassType.EMBEDDABLE;
//			} else if (clazz
//					.isAnnotationPresent(javax.persistence.MappedSuperclass.class)) {
//				type = AnnotatedClassType.EMBEDDABLE_SUPERCLASS;
//			} else {
//				type = AnnotatedClassType.NONE;
//			}
//			classTypes.put(clazz.getName(), type);
//			return type;
//		}
//
//		/**
//		 * {@inheritDoc}
//		 */
//		public Map<Table, List<String[]>> getTableUniqueConstraints() {
//			final Map<Table, List<String[]>> deprecatedStructure = new HashMap<Table, List<String[]>>(
//					CollectionHelper
//							.determineProperSizing(getUniqueConstraintHoldersByTable()),
//					CollectionHelper.LOAD_FACTOR);
//			for (Map.Entry<Table, List<UniqueConstraintHolder>> entry : getUniqueConstraintHoldersByTable()
//					.entrySet()) {
//				List<String[]> columnsPerConstraint = new ArrayList<String[]>(
//						CollectionHelper.determineProperSizing(entry.getValue()
//								.size()));
//				deprecatedStructure.put(entry.getKey(), columnsPerConstraint);
//				for (UniqueConstraintHolder holder : entry.getValue()) {
//					columnsPerConstraint.add(holder.getColumns());
//				}
//			}
//			return deprecatedStructure;
//		}
//
//		public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable() {
//			return uniqueConstraintHoldersByTable;
//		}
//
//		@SuppressWarnings({ "unchecked" })
//		public void addUniqueConstraints(Table table, List uniqueConstraints) {
//			List<UniqueConstraintHolder> constraintHolders = new ArrayList<UniqueConstraintHolder>(
//					CollectionHelper.determineProperSizing(uniqueConstraints
//							.size()));
//
//			int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders(table);
//			for (String[] columns : (List<String[]>) uniqueConstraints) {
//				final String keyName = "key" + keyNameBase++;
//				constraintHolders.add(new UniqueConstraintHolder().setName(
//						keyName).setColumns(columns));
//			}
//			addUniqueConstraintHolders(table, constraintHolders);
//		}
//
//		private int determineCurrentNumberOfUniqueConstraintHolders(Table table) {
//			List currentHolders = getUniqueConstraintHoldersByTable()
//					.get(table);
//			return currentHolders == null ? 0 : currentHolders.size();
//		}
//
//		public void addUniqueConstraintHolders(Table table,
//				List<UniqueConstraintHolder> uniqueConstraintHolders) {
//			List<UniqueConstraintHolder> holderList = getUniqueConstraintHoldersByTable()
//					.get(table);
//			if (holderList == null) {
//				holderList = new ArrayList<UniqueConstraintHolder>();
//				getUniqueConstraintHoldersByTable().put(table, holderList);
//			}
//			holderList.addAll(uniqueConstraintHolders);
//		}
//
//		public void addMappedBy(String entityName, String propertyName,
//				String inversePropertyName) {
//			mappedByResolver.put(entityName + "." + propertyName,
//					inversePropertyName);
//		}
//
//		public String getFromMappedBy(String entityName, String propertyName) {
//			return mappedByResolver.get(entityName + "." + propertyName);
//		}
//
//		public void addPropertyReferencedAssociation(String entityName,
//				String propertyName, String propertyRef) {
//			propertyRefResolver.put(entityName + "." + propertyName,
//					propertyRef);
//		}
//
//		public String getPropertyReferencedAssociation(String entityName,
//				String propertyName) {
//			return propertyRefResolver.get(entityName + "." + propertyName);
//		}
//
//		public ReflectionManager getReflectionManager() {
//			return reflectionManager;
//		}
//
//		public Map getClasses() {
//			return classes;
//		}
//
//		public void addAnyMetaDef(AnyMetaDef defAnn) throws AnnotationException {
//			if (anyMetaDefs.containsKey(defAnn.name())) {
//				throw new AnnotationException(
//						"Two @AnyMetaDef with the same name defined: "
//								+ defAnn.name());
//			}
//			anyMetaDefs.put(defAnn.name(), defAnn);
//		}
//
//		public AnyMetaDef getAnyMetaDef(String name) {
//			return anyMetaDefs.get(name);
//		}
//	}
//
//	final ObjectNameNormalizer normalizer = new ObjectNameNormalizerImpl();
//
//	final class ObjectNameNormalizerImpl extends ObjectNameNormalizer implements
//			Serializable {
//		public boolean isUseQuotedIdentifiersGlobally() {
//			// Do not cache this value as we lazily set it in Hibernate
//			// Annotation (AnnotationMyConfiguration)
//			// TODO use a dedicated protected useQuotedIdentifier flag in
//			// MyConfiguration (overriden by AnnotationMyConfiguration)
//			String setting = (String) properties
//					.get(Environment.GLOBALLY_QUOTED_IDENTIFIERS);
//			return setting != null && Boolean.valueOf(setting).booleanValue();
//		}
//
//		public NamingStrategy getNamingStrategy() {
//			return namingStrategy;
//		}
//	}
//
//	protected class MetadataSourceQueue implements Serializable {
//		private LinkedHashMap<XmlDocument, Set<String>> hbmMetadataToEntityNamesMap = new LinkedHashMap<XmlDocument, Set<String>>();
//		private Map<String, XmlDocument> hbmMetadataByEntityNameXRef = new HashMap<String, XmlDocument>();
//
//		// XClass are not serializable by default
//		private transient List<XClass> annotatedClasses = new ArrayList<XClass>();
//		// only used during the secondPhaseCompile pass, hence does not need to
//		// be serialized
//		private transient Map<String, XClass> annotatedClassesByEntityNameMap = new HashMap<String, XClass>();
//
//		private void readObject(ObjectInputStream ois) throws IOException,
//				ClassNotFoundException {
//			ois.defaultReadObject();
//			annotatedClassesByEntityNameMap = new HashMap<String, XClass>();
//
//			// build back annotatedClasses
//			@SuppressWarnings("unchecked")
//			List<Class> serializableAnnotatedClasses = (List<Class>) ois
//					.readObject();
//			annotatedClasses = new ArrayList<XClass>(
//					serializableAnnotatedClasses.size());
//			for (Class clazz : serializableAnnotatedClasses) {
//				annotatedClasses.add(reflectionManager.toXClass(clazz));
//			}
//		}
//
//		private void writeObject(java.io.ObjectOutputStream out)
//				throws IOException {
//			out.defaultWriteObject();
//			List<Class> serializableAnnotatedClasses = new ArrayList<Class>(
//					annotatedClasses.size());
//			for (XClass xClass : annotatedClasses) {
//				serializableAnnotatedClasses.add(reflectionManager
//						.toClass(xClass));
//			}
//			out.writeObject(serializableAnnotatedClasses);
//		}
//
//		public void add(XmlDocument metadataXml) {
//			final Document document = metadataXml.getDocumentTree();
//			final Element hmNode = document.getRootElement();
//			Attribute packNode = hmNode.attribute("package");
//			String defaultPackage = packNode != null ? packNode.getValue() : "";
//			Set<String> entityNames = new HashSet<String>();
//			findClassNames(defaultPackage, hmNode, entityNames);
//			for (String entity : entityNames) {
//				hbmMetadataByEntityNameXRef.put(entity, metadataXml);
//			}
//			this.hbmMetadataToEntityNamesMap.put(metadataXml, entityNames);
//		}
//
//		private void findClassNames(String defaultPackage, Element startNode,
//				Set<String> names) {
//			// if we have some extends we need to check if those classes
//			// possibly could be inside the
//			// same hbm.xml file...
//			Iterator[] classes = new Iterator[4];
//			classes[0] = startNode.elementIterator("class");
//			classes[1] = startNode.elementIterator("subclass");
//			classes[2] = startNode.elementIterator("joined-subclass");
//			classes[3] = startNode.elementIterator("union-subclass");
//
//			Iterator classIterator = new JoinedIterator(classes);
//			while (classIterator.hasNext()) {
//				Element element = (Element) classIterator.next();
//				String entityName = element.attributeValue("entity-name");
//				if (entityName == null) {
//					entityName = getClassName(element.attribute("name"),
//							defaultPackage);
//				}
//				names.add(entityName);
//				findClassNames(defaultPackage, element, names);
//			}
//		}
//
//		private String getClassName(Attribute name, String defaultPackage) {
//			if (name == null) {
//				return null;
//			}
//			String unqualifiedName = name.getValue();
//			if (unqualifiedName == null) {
//				return null;
//			}
//			if (unqualifiedName.indexOf('.') < 0 && defaultPackage != null) {
//				return defaultPackage + '.' + unqualifiedName;
//			}
//			return unqualifiedName;
//		}
//
//		public void add(XClass annotatedClass) {
//			annotatedClasses.add(annotatedClass);
//		}
//
//		protected void syncAnnotatedClasses() {
//			final Iterator<XClass> itr = annotatedClasses.iterator();
//			while (itr.hasNext()) {
//				final XClass annotatedClass = itr.next();
//				if (annotatedClass.isAnnotationPresent(Entity.class)) {
//					annotatedClassesByEntityNameMap.put(
//							annotatedClass.getName(), annotatedClass);
//					continue;
//				}
//
//				if (!annotatedClass
//						.isAnnotationPresent(javax.persistence.MappedSuperclass.class)) {
//					itr.remove();
//				}
//			}
//		}
//
//		protected void processMetadata(List<MetadataSourceType> order) {
//			syncAnnotatedClasses();
//
//			for (MetadataSourceType type : order) {
//				if (MetadataSourceType.HBM.equals(type)) {
//					processHbmXmlQueue();
//				} else if (MetadataSourceType.CLASS.equals(type)) {
//					processAnnotatedClassesQueue();
//				}
//			}
//		}
//
//		private void processHbmXmlQueue() {
//			log.debug("Processing hbm.xml files");
//			for (Map.Entry<XmlDocument, Set<String>> entry : hbmMetadataToEntityNamesMap
//					.entrySet()) {
//				// Unfortunately we have to create a Mappings instance for each
//				// iteration here
//				processHbmXml(entry.getKey(), entry.getValue());
//			}
//			hbmMetadataToEntityNamesMap.clear();
//			hbmMetadataByEntityNameXRef.clear();
//		}
//
//		private void processHbmXml(XmlDocument metadataXml,
//				Set<String> entityNames) {
//			try {
//				HbmBinder.bindRoot(metadataXml, createMappings(),
//						CollectionHelper.EMPTY_MAP, entityNames);
//			} catch (MappingException me) {
//				throw new InvalidMappingException(metadataXml.getOrigin()
//						.getType(), metadataXml.getOrigin().getName(), me);
//			}
//
//			for (String entityName : entityNames) {
//				if (annotatedClassesByEntityNameMap.containsKey(entityName)) {
//					annotatedClasses.remove(annotatedClassesByEntityNameMap
//							.get(entityName));
//					annotatedClassesByEntityNameMap.remove(entityName);
//				}
//			}
//		}
//
//		private void processAnnotatedClassesQueue() {
//			log.debug("Process annotated classes");
//			// bind classes in the correct order calculating some inheritance
//			// state
//			List<XClass> orderedClasses = orderAndFillHierarchy(annotatedClasses);
//			Mappings mappings = createMappings();
//			Map<XClass, InheritanceState> inheritanceStatePerClass = AnnotationBinder
//					.buildInheritanceStates(orderedClasses, mappings);
//
//			for (XClass clazz : orderedClasses) {
//				AnnotationBinder.bindClass(clazz, inheritanceStatePerClass,
//						mappings);
//
//				final String entityName = clazz.getName();
//				if (hbmMetadataByEntityNameXRef.containsKey(entityName)) {
//					hbmMetadataToEntityNamesMap
//							.remove(hbmMetadataByEntityNameXRef.get(entityName));
//					hbmMetadataByEntityNameXRef.remove(entityName);
//				}
//			}
//			annotatedClasses.clear();
//			annotatedClassesByEntityNameMap.clear();
//		}
//
//		private List<XClass> orderAndFillHierarchy(List<XClass> original) {
//			List<XClass> copy = new ArrayList<XClass>(original);
//			insertMappedSuperclasses(original, copy);
//
//			// order the hierarchy
//			List<XClass> workingCopy = new ArrayList<XClass>(copy);
//			List<XClass> newList = new ArrayList<XClass>(copy.size());
//			while (workingCopy.size() > 0) {
//				XClass clazz = workingCopy.get(0);
//				orderHierarchy(workingCopy, newList, copy, clazz);
//			}
//			return newList;
//		}
//
//		private void insertMappedSuperclasses(List<XClass> original,
//				List<XClass> copy) {
//			for (XClass clazz : original) {
//				XClass superClass = clazz.getSuperclass();
//				while (superClass != null
//						&& !reflectionManager.equals(superClass, Object.class)
//						&& !copy.contains(superClass)) {
//					if (superClass.isAnnotationPresent(Entity.class)
//							|| superClass
//									.isAnnotationPresent(javax.persistence.MappedSuperclass.class)) {
//						copy.add(superClass);
//					}
//					superClass = superClass.getSuperclass();
//				}
//			}
//		}
//
//		private void orderHierarchy(List<XClass> copy, List<XClass> newList,
//				List<XClass> original, XClass clazz) {
//			if (clazz == null || reflectionManager.equals(clazz, Object.class)) {
//				return;
//			}
//			// process superclass first
//			orderHierarchy(copy, newList, original, clazz.getSuperclass());
//			if (original.contains(clazz)) {
//				if (!newList.contains(clazz)) {
//					newList.add(clazz);
//				}
//				copy.remove(clazz);
//			}
//		}
//
//		public boolean isEmpty() {
//			return hbmMetadataToEntityNamesMap.isEmpty()
//					&& annotatedClasses.isEmpty();
//		}
//
//	}
//
//	public static final MetadataSourceType[] DEFAULT_ARTEFACT_PROCESSING_ORDER = new MetadataSourceType[] {
//			MetadataSourceType.HBM, MetadataSourceType.CLASS };
//
//	private List<MetadataSourceType> metadataSourcePrecedence;
//
//	private List<MetadataSourceType> determineMetadataSourcePrecedence() {
//		if (metadataSourcePrecedence.isEmpty()
//				&& StringHelper.isNotEmpty(getProperties().getProperty(
//						ARTEFACT_PROCESSING_ORDER))) {
//			metadataSourcePrecedence = parsePrecedence(getProperties()
//					.getProperty(ARTEFACT_PROCESSING_ORDER));
//		}
//		if (metadataSourcePrecedence.isEmpty()) {
//			metadataSourcePrecedence = Arrays
//					.asList(DEFAULT_ARTEFACT_PROCESSING_ORDER);
//		}
//		metadataSourcePrecedence = Collections
//				.unmodifiableList(metadataSourcePrecedence);
//
//		return metadataSourcePrecedence;
//	}
//
//	public void setPrecedence(String precedence) {
//		this.metadataSourcePrecedence = parsePrecedence(precedence);
//	}
//
//	private List<MetadataSourceType> parsePrecedence(String s) {
//		if (StringHelper.isEmpty(s)) {
//			return Collections.emptyList();
//		}
//		StringTokenizer precedences = new StringTokenizer(s, ",; ", false);
//		List<MetadataSourceType> tmpPrecedences = new ArrayList<MetadataSourceType>();
//		while (precedences.hasMoreElements()) {
//			tmpPrecedences.add(MetadataSourceType
//					.parsePrecedence((String) precedences.nextElement()));
//		}
//		return tmpPrecedences;
//	}
//
//	private static class CacheHolder {
//		public CacheHolder(String role, String usage, String region,
//				boolean isClass, boolean cacheLazy) {
//			this.role = role;
//			this.usage = usage;
//			this.region = region;
//			this.isClass = isClass;
//			this.cacheLazy = cacheLazy;
//		}
//
//		public String role;
//		public String usage;
//		public String region;
//		public boolean isClass;
//		public boolean cacheLazy;
//	}
//}
